//===--- Deserialization.cpp - Loading a serialized AST -------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "polarphp/serialization/internal/BCReadingExtras.h"
#include "polarphp/serialization/internal/DeserializationErrors.h"
#include "polarphp/serialization/internal/ModuleFile.h"
#include "polarphp/serialization/internal/ModuleFormat.h"
#include "polarphp/ast/AstContext.h"
#include "polarphp/ast/AutoDiff.h"
#include "polarphp/ast/DiagnosticsSema.h"
#include "polarphp/ast/Expr.h"
#include "polarphp/ast/ForeignErrorConvention.h"
#include "polarphp/ast/GenericEnvironment.h"
#include "polarphp/ast/Initializer.h"
#include "polarphp/ast/NameLookupRequests.h"
#include "polarphp/ast/Pattern.h"
#include "polarphp/ast/ParameterList.h"
#include "polarphp/ast/PrettyStackTrace.h"
#include "polarphp/ast/PropertyWrappers.h"
#include "polarphp/ast/InterfaceConformance.h"
#include "polarphp/ast/TypeCheckRequests.h"
#include "polarphp/clangimporter/ClangImporter.h"
#include "polarphp/clangimporter/ClangModule.h"
#include "polarphp/serialization/SerializedModuleLoader.h"
#include "polarphp/basic/Defer.h"
#include "polarphp/basic/Statistic.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

#define DEBUG_TYPE "Serialization"

STATISTIC(NumDeclsLoaded, "# of decls deserialized");
STATISTIC(NumMemberListsLoaded,
          "# of nominals/extensions whose members were loaded");
STATISTIC(NumNormalInterfaceConformancesLoaded,
          "# of normal protocol conformances deserialized");
STATISTIC(NumNormalInterfaceConformancesCompleted,
          "# of normal protocol conformances completed");
STATISTIC(NumNestedTypeShortcuts,
          "# of nested types resolved without full lookup");

using namespace polar;
using namespace polar::serialization;
using llvm::Expected;

StringRef polar::getNameOfModule(const ModuleFile *MF) {
   return MF->Name;
}

namespace {
struct DeclAndOffset {
   const Decl *D;
   uint64_t offset;
};

static raw_ostream &operator<<(raw_ostream &os, DeclAndOffset &&pair) {
   return os << Decl::getKindName(pair.D->getKind())
             << "Decl @ " << pair.offset;
}

class PrettyDeclDeserialization : public llvm::PrettyStackTraceEntry {
   const ModuleFile *MF;
   const ModuleFile::Serialized<Decl*> &DeclOrOffset;
   uint64_t offset;
   decls_block::RecordKind Kind;
public:
   PrettyDeclDeserialization(ModuleFile *module,
                             const ModuleFile::Serialized<Decl*> &declOrOffset,
                             decls_block::RecordKind kind)
      : MF(module), DeclOrOffset(declOrOffset), offset(declOrOffset),
        Kind(kind) {
   }

   static const char *getRecordKindString(decls_block::RecordKind Kind) {
      switch (Kind) {
#define RECORD(Id) case decls_block::Id: return #Id;
#include "polarphp/serialization/internal/DeclTypeRecordNodesDef.h"
      }

      llvm_unreachable("Unhandled RecordKind in switch.");
   }

   void print(raw_ostream &os) const override {
      if (!DeclOrOffset.isComplete()) {
         os << "While deserializing decl @ " << offset << " ("
            << getRecordKindString(Kind) << ")";
      } else {
         os << "While deserializing ";

         if (auto VD = dyn_cast<ValueDecl>(DeclOrOffset.get())) {
            os << "'" << VD->getBaseName() << "' (" << DeclAndOffset{VD, offset}
               << ")";
         } else if (auto ED = dyn_cast<ExtensionDecl>(DeclOrOffset.get())) {
            os << "extension of '" << ED->getExtendedType() << "' ("
               << DeclAndOffset{ED, offset} << ")";
         } else {
            os << DeclAndOffset{DeclOrOffset.get(), offset};
         }
      }
      os << " in '" << getNameOfModule(MF) << "'\n";
   }
};

class PrettyXRefTrace :
   public llvm::PrettyStackTraceEntry,
   public XRefTracePath {
public:
   explicit PrettyXRefTrace(ModuleDecl &M) : XRefTracePath(M) {}

   void print(raw_ostream &os) const override {
      XRefTracePath::print(os, "\t");
   }
};
} // end anonymous namespace

const char DeclDeserializationError::ID = '\0';
void DeclDeserializationError::anchor() {}
const char XRefError::ID = '\0';
void XRefError::anchor() {}
const char XRefNonLoadedModuleError::ID = '\0';
void XRefNonLoadedModuleError::anchor() {}
const char OverrideError::ID = '\0';
void OverrideError::anchor() {}
const char TypeError::ID = '\0';
void TypeError::anchor() {}
const char ExtensionError::ID = '\0';
void ExtensionError::anchor() {}
const char DeclAttributesDidNotMatch::ID = '\0';
void DeclAttributesDidNotMatch::anchor() {}

/// Skips a single record in the bitstream.
///
/// Destroys the stream position if the next entry is not a record.
static void skipRecord(llvm::BitstreamCursor &cursor, unsigned recordKind) {
   auto next = llvm::cantFail<llvm::BitstreamEntry>(
      cursor.advance(AF_DontPopBlockAtEnd));
   assert(next.Kind == llvm::BitstreamEntry::Record);

   unsigned kind = llvm::cantFail<unsigned>(cursor.skipRecord(next.ID));
   assert(kind == recordKind);
   (void)kind;
}

void ModuleFile::fatal(llvm::Error error) {
   if (FileContext) {
      getContext().Diags.diagnose(SourceLoc(), diag::serialization_fatal, Name);

      if (!CompatibilityVersion.empty()) {
         if (getContext().LangOpts.EffectiveLanguageVersion
             != CompatibilityVersion) {
            SmallString<16> effectiveVersionBuffer, compatVersionBuffer;
            {
               llvm::raw_svector_ostream out(effectiveVersionBuffer);
               out << getContext().LangOpts.EffectiveLanguageVersion;
            }
            {
               llvm::raw_svector_ostream out(compatVersionBuffer);
               out << CompatibilityVersion;
            }
            getContext().Diags.diagnose(
               SourceLoc(), diag::serialization_compatibility_version_mismatch,
               effectiveVersionBuffer, Name, compatVersionBuffer);
         }
      }
   }

   logAllUnhandledErrors(std::move(error), llvm::errs(),
                         "\n*** DESERIALIZATION FAILURE (please include this "
                         "section in any bug report) ***\n");
   abort();
}

static Optional<polar::AccessorKind>
getActualAccessorKind(uint8_t raw) {
   switch (serialization::AccessorKind(raw)) {
#define ACCESSOR(ID) \
  case serialization::AccessorKind::ID: return polar::AccessorKind::ID;
#include "polarphp/ast/AccessorKindsDef.h"
   }

   return None;
}

/// Translate from the serialization DefaultArgumentKind enumerators, which are
/// guaranteed to be stable, to the AST ones.
static Optional<polar::DefaultArgumentKind>
getActualDefaultArgKind(uint8_t raw) {
   switch (static_cast<serialization::DefaultArgumentKind>(raw)) {
      case serialization::DefaultArgumentKind::None:
         return polar::DefaultArgumentKind::None;
      case serialization::DefaultArgumentKind::Normal:
         return polar::DefaultArgumentKind::Normal;
      case serialization::DefaultArgumentKind::Inherited:
         return polar::DefaultArgumentKind::Inherited;
      case serialization::DefaultArgumentKind::Column:
         return polar::DefaultArgumentKind::Column;
      case serialization::DefaultArgumentKind::File:
         return polar::DefaultArgumentKind::File;
      case serialization::DefaultArgumentKind::Line:
         return polar::DefaultArgumentKind::Line;
      case serialization::DefaultArgumentKind::Function:
         return polar::DefaultArgumentKind::Function;
      case serialization::DefaultArgumentKind::DSOHandle:
         return polar::DefaultArgumentKind::DSOHandle;
      case serialization::DefaultArgumentKind::NilLiteral:
         return polar::DefaultArgumentKind::NilLiteral;
      case serialization::DefaultArgumentKind::EmptyArray:
         return polar::DefaultArgumentKind::EmptyArray;
      case serialization::DefaultArgumentKind::EmptyDictionary:
         return polar::DefaultArgumentKind::EmptyDictionary;
      case serialization::DefaultArgumentKind::StoredProperty:
         return polar::DefaultArgumentKind::StoredProperty;
   }
   return None;
}

ParameterList *ModuleFile::readParameterList() {
   using namespace decls_block;

   SmallVector<uint64_t, 8> scratch;
   llvm::BitstreamEntry entry =
      fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
   unsigned recordID =
      fatalIfUnexpected(DeclTypeCursor.readRecord(entry.ID, scratch));
   assert(recordID == PARAMETERLIST);
   (void) recordID;

   ArrayRef<uint64_t> rawMemberIDs;
   decls_block::ParameterListLayout::readRecord(scratch, rawMemberIDs);

   SmallVector<ParamDecl *, 8> params;
   for (DeclID paramID : rawMemberIDs)
      params.push_back(cast<ParamDecl>(getDecl(paramID)));

   return ParameterList::create(getContext(), params);
}

Expected<Pattern *> ModuleFile::readPattern(DeclContext *owningDC) {
   // Currently, the only case in which this function can fail (return an error)
   // is when reading a pattern for a single variable declaration.

   using namespace decls_block;

   auto readPatternUnchecked = [this](DeclContext *owningDC) -> Pattern * {
      Expected<Pattern *> deserialized = readPattern(owningDC);
      if (!deserialized) {
         fatal(deserialized.takeError());
      }
      assert(deserialized.get());
      return deserialized.get();
   };

   SmallVector<uint64_t, 8> scratch;

   BCOffsetRAII restoreOffset(DeclTypeCursor);
   llvm::BitstreamEntry next =
      fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
   if (next.Kind != llvm::BitstreamEntry::Record)
      fatal();

   /// Local function to record the type of this pattern.
   auto recordPatternType = [&](Pattern *pattern, Type type) {
      if (type->hasTypeParameter())
         pattern->setDelayedInterfaceType(type, owningDC);
      else
         pattern->setType(type);
   };

   unsigned kind =
      fatalIfUnexpected(DeclTypeCursor.readRecord(next.ID, scratch));
   switch (kind) {
      case decls_block::PAREN_PATTERN: {
         bool isImplicit;
         ParenPatternLayout::readRecord(scratch, isImplicit);

         Pattern *subPattern = readPatternUnchecked(owningDC);

         auto result = new (getContext()) ParenPattern(SourceLoc(),
                                                       subPattern,
                                                       SourceLoc(),
                                                       isImplicit);

         if (Type interfaceType = subPattern->getDelayedInterfaceType())
            result->setDelayedInterfaceType(ParenType::get(getContext(),
                                                           interfaceType), owningDC);
         else
            result->setType(ParenType::get(getContext(), subPattern->getType()));
         restoreOffset.reset();
         return result;
      }
      case decls_block::TUPLE_PATTERN: {
         TypeID tupleTypeID;
         unsigned count;
         bool isImplicit;

         TuplePatternLayout::readRecord(scratch, tupleTypeID, count, isImplicit);

         SmallVector<TuplePatternElt, 8> elements;
         for ( ; count > 0; --count) {
            scratch.clear();
            next = fatalIfUnexpected(DeclTypeCursor.advance());
            assert(next.Kind == llvm::BitstreamEntry::Record);

            kind = fatalIfUnexpected(DeclTypeCursor.readRecord(next.ID, scratch));
            assert(kind == decls_block::TUPLE_PATTERN_ELT);

            // FIXME: Add something for this record or remove it.
            IdentifierID labelID;
            TuplePatternEltLayout::readRecord(scratch, labelID);
            Identifier label = getIdentifier(labelID);

            Pattern *subPattern = readPatternUnchecked(owningDC);
            elements.push_back(TuplePatternElt(label, SourceLoc(), subPattern));
         }

         auto result = TuplePattern::create(getContext(), SourceLoc(),
                                            elements, SourceLoc(), isImplicit);
         recordPatternType(result, getType(tupleTypeID));
         restoreOffset.reset();
         return result;
      }
      case decls_block::NAMED_PATTERN: {
         DeclID varID;
         TypeID typeID;
         bool isImplicit;
         NamedPatternLayout::readRecord(scratch, varID, typeID, isImplicit);

         auto deserialized = getDeclChecked(varID);
         if (!deserialized) {
            // Pass through the error. It's too bad that it affects the whole pattern,
            // but that's what we get.
            return deserialized.takeError();
         }

         auto var = cast<VarDecl>(deserialized.get());
         auto result = new (getContext()) NamedPattern(var, isImplicit);
         recordPatternType(result, getType(typeID));
         restoreOffset.reset();
         return result;
      }
      case decls_block::ANY_PATTERN: {
         TypeID typeID;
         bool isImplicit;

         AnyPatternLayout::readRecord(scratch, typeID, isImplicit);
         auto result = new (getContext()) AnyPattern(SourceLoc(), isImplicit);
         recordPatternType(result, getType(typeID));
         restoreOffset.reset();
         return result;
      }
      case decls_block::TYPED_PATTERN: {
         TypeID typeID;
         bool isImplicit;
         TypedPatternLayout::readRecord(scratch, typeID, isImplicit);

         Expected<Pattern *> subPattern = readPattern(owningDC);
         if (!subPattern) {
            // Pass through any errors.
            return subPattern;
         }

         auto type = getType(typeID);
         auto result = new (getContext()) TypedPattern(subPattern.get(),
            /*typeRepr*/nullptr,
                                                       isImplicit);
         recordPatternType(result, type);
         restoreOffset.reset();
         return result;
      }
      case decls_block::VAR_PATTERN: {
         bool isImplicit, isLet;
         VarPatternLayout::readRecord(scratch, isLet, isImplicit);

         Pattern *subPattern = readPatternUnchecked(owningDC);

         auto result = new (getContext()) VarPattern(SourceLoc(), isLet, subPattern,
                                                     isImplicit);
         if (Type interfaceType = subPattern->getDelayedInterfaceType())
            result->setDelayedInterfaceType(interfaceType, owningDC);
         else
            result->setType(subPattern->getType());
         restoreOffset.reset();
         return result;
      }

      default:
         return nullptr;
   }
}

PILLayout *ModuleFile::readPILLayout(llvm::BitstreamCursor &Cursor) {
   using namespace decls_block;

   SmallVector<uint64_t, 16> scratch;

   llvm::BitstreamEntry next =
      fatalIfUnexpected(Cursor.advance(AF_DontPopBlockAtEnd));
   assert(next.Kind == llvm::BitstreamEntry::Record);

   unsigned kind = fatalIfUnexpected(Cursor.readRecord(next.ID, scratch));
   switch (kind) {
      case decls_block::PIL_LAYOUT: {
         GenericSignatureID rawGenericSig;
         unsigned numFields;
         ArrayRef<uint64_t> types;
         decls_block::PILLayoutLayout::readRecord(scratch, rawGenericSig,
                                                  numFields, types);

         SmallVector<PILField, 4> fields;
         for (auto fieldInfo : types.slice(0, numFields)) {
            bool isMutable = fieldInfo & 0x80000000U;
            auto typeId = fieldInfo & 0x7FFFFFFFU;
            fields.push_back(
               PILField(getType(typeId)->getCanonicalType(),
                        isMutable));
         }

         CanGenericSignature canSig;
         if (auto sig = getGenericSignature(rawGenericSig))
            canSig = sig->getCanonicalSignature();
         return PILLayout::get(getContext(), canSig, fields);
      }
      default:
         fatal();
   }
}

InterfaceConformanceRef ModuleFile::readConformance(
   llvm::BitstreamCursor &Cursor,
   GenericEnvironment *genericEnv) {
   auto conformance = readConformanceChecked(Cursor, genericEnv);
   if (!conformance)
      fatal(conformance.takeError());
   return conformance.get();
}

Expected<InterfaceConformanceRef>
ModuleFile::readConformanceChecked(llvm::BitstreamCursor &Cursor,
                                   GenericEnvironment *genericEnv) {
   using namespace decls_block;

   SmallVector<uint64_t, 16> scratch;

   llvm::BitstreamEntry next =
      fatalIfUnexpected(Cursor.advance(AF_DontPopBlockAtEnd));
   assert(next.Kind == llvm::BitstreamEntry::Record);

   if (getContext().Stats)
      getContext().Stats->getFrontendCounters().NumConformancesDeserialized++;

   unsigned kind = fatalIfUnexpected(Cursor.readRecord(next.ID, scratch));
   switch (kind) {
      case INVALID_PROTOCOL_CONFORMANCE: {
         return InterfaceConformanceRef::forInvalid();
      }

      case ABSTRACT_PROTOCOL_CONFORMANCE: {
         DeclID protoID;
         AbstractInterfaceConformanceLayout::readRecord(scratch, protoID);

         auto decl = getDeclChecked(protoID);
         if (!decl)
            return decl.takeError();

         auto proto = cast<InterfaceDecl>(decl.get());
         return InterfaceConformanceRef(proto);
      }

      case SELF_PROTOCOL_CONFORMANCE: {
         DeclID protoID;
         SelfInterfaceConformanceLayout::readRecord(scratch, protoID);

         auto decl = getDeclChecked(protoID);
         if (!decl)
            return decl.takeError();

         auto proto = cast<InterfaceDecl>(decl.get());
         auto conformance = getContext().getSelfConformance(proto);
         return InterfaceConformanceRef(conformance);
      }

      case SPECIALIZED_PROTOCOL_CONFORMANCE: {
         TypeID conformingTypeID;
         SubstitutionMapID substitutionMapID;
         SpecializedInterfaceConformanceLayout::readRecord(scratch, conformingTypeID,
                                                          substitutionMapID);

         AstContext &ctx = getContext();
         Type conformingType = getType(conformingTypeID);
         if (genericEnv) {
            conformingType = genericEnv->mapTypeIntoContext(conformingType);
         }

         PrettyStackTraceType trace(getAssociatedModule()->getAstContext(),
                                    "reading specialized conformance for",
                                    conformingType);

         auto subMap = getSubstitutionMap(substitutionMapID);

         InterfaceConformanceRef genericConformance =
            readConformance(Cursor, genericEnv);
         PrettyStackTraceDecl traceTo("... to", genericConformance.getRequirement());

         assert(genericConformance.isConcrete() && "Abstract generic conformance?");
         auto conformance =
            ctx.getSpecializedConformance(conformingType,
                                          genericConformance.getConcrete(),
                                          subMap);
         return InterfaceConformanceRef(conformance);
      }

      case INHERITED_PROTOCOL_CONFORMANCE: {
         TypeID conformingTypeID;
         InheritedInterfaceConformanceLayout::readRecord(scratch, conformingTypeID);

         AstContext &ctx = getContext();
         Type conformingType = getType(conformingTypeID);
         if (genericEnv) {
            conformingType = genericEnv->mapTypeIntoContext(conformingType);
         }

         PrettyStackTraceType trace(getAssociatedModule()->getAstContext(),
                                    "reading inherited conformance for",
                                    conformingType);

         InterfaceConformanceRef inheritedConformance =
            readConformance(Cursor, genericEnv);
         PrettyStackTraceDecl traceTo("... to",
                                      inheritedConformance.getRequirement());

         assert(inheritedConformance.isConcrete() &&
                "Abstract inherited conformance?");
         auto conformance =
            ctx.getInheritedConformance(conformingType,
                                        inheritedConformance.getConcrete());
         return InterfaceConformanceRef(conformance);
      }

      case NORMAL_PROTOCOL_CONFORMANCE_ID: {
         NormalConformanceID conformanceID;
         NormalInterfaceConformanceIdLayout::readRecord(scratch, conformanceID);
         return InterfaceConformanceRef(readNormalConformance(conformanceID));
      }

      case PROTOCOL_CONFORMANCE_XREF: {
         DeclID protoID;
         DeclID nominalID;
         ModuleID moduleID;
         InterfaceConformanceXrefLayout::readRecord(scratch, protoID, nominalID,
                                                   moduleID);

         auto nominal = cast<NominalTypeDecl>(getDecl(nominalID));
         PrettyStackTraceDecl trace("cross-referencing conformance for", nominal);
         auto proto = cast<InterfaceDecl>(getDecl(protoID));
         PrettyStackTraceDecl traceTo("... to", proto);
         auto module = getModule(moduleID);

         // FIXME: If the module hasn't been loaded, we probably don't want to fall
         // back to the current module like this.
         if (!module)
            module = getAssociatedModule();

         SmallVector<InterfaceConformance *, 2> conformances;
         nominal->lookupConformance(module, proto, conformances);
         PrettyStackTraceModuleFile traceMsg(
            "If you're seeing a crash here, check that your SDK and dependencies "
            "are at least as new as the versions used to build", *this);
         // This would normally be an assertion but it's more useful to print the
         // PrettyStackTrace here even in no-asserts builds.
         if (conformances.empty())
            abort();
         return InterfaceConformanceRef(conformances.front());
      }

         // Not a protocol conformance.
      default:
         fatal();
   }
}

NormalInterfaceConformance *ModuleFile::readNormalConformance(
   NormalConformanceID conformanceID) {
   auto &conformanceEntry = NormalConformances[conformanceID-1];
   if (conformanceEntry.isComplete()) {
      return conformanceEntry.get();
   }

   using namespace decls_block;

   // Find the conformance record.
   BCOffsetRAII restoreOffset(DeclTypeCursor);
   fatalIfNotSuccess(DeclTypeCursor.JumpToBit(conformanceEntry));
   llvm::BitstreamEntry entry = fatalIfUnexpected(DeclTypeCursor.advance());
   if (entry.Kind != llvm::BitstreamEntry::Record)
      fatal();

   DeclID protoID;
   DeclContextID contextID;
   unsigned valueCount, typeCount, conformanceCount;
   ArrayRef<uint64_t> rawIDs;
   SmallVector<uint64_t, 16> scratch;

   unsigned kind =
      fatalIfUnexpected(DeclTypeCursor.readRecord(entry.ID, scratch));
   if (kind != NORMAL_PROTOCOL_CONFORMANCE)
      fatal();

   NormalInterfaceConformanceLayout::readRecord(scratch, protoID,
                                               contextID, typeCount,
                                               valueCount, conformanceCount,
                                               rawIDs);

   AstContext &ctx = getContext();
   DeclContext *dc = getDeclContext(contextID);
   assert(!isa<ClangModuleUnit>(dc->getModuleScopeContext())
          && "should not have serialized a conformance from a clang module");
   Type conformingType = dc->getDeclaredInterfaceType();
   PrettyStackTraceType trace(ctx, "reading conformance for", conformingType);

   auto proto = cast<InterfaceDecl>(getDecl(protoID));
   PrettyStackTraceDecl traceTo("... to", proto);
   ++NumNormalInterfaceConformancesLoaded;

   auto conformance = ctx.getConformance(conformingType, proto, SourceLoc(), dc,
                                         InterfaceConformanceState::Incomplete);

   // Record this conformance.
   if (conformanceEntry.isComplete())
      return conformance;

   uint64_t offset = conformanceEntry;
   conformanceEntry = conformance;

   dc->getSelfNominalTypeDecl()->registerInterfaceConformance(conformance);

   // If the conformance is complete, we're done.
   if (conformance->isComplete())
      return conformance;

   conformance->setState(InterfaceConformanceState::Complete);
   conformance->setLazyLoader(this, offset);
   return conformance;
}

GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC) {
   using namespace decls_block;

   assert(DC && "need a context for the decls in the list");

   BCOffsetRAII lastRecordOffset(DeclTypeCursor);
   SmallVector<uint64_t, 8> scratch;
   StringRef blobData;

   llvm::BitstreamEntry next =
      fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
   if (next.Kind != llvm::BitstreamEntry::Record)
      return nullptr;

   unsigned kind =
      fatalIfUnexpected(DeclTypeCursor.readRecord(next.ID, scratch, &blobData));
   if (kind != GENERIC_PARAM_LIST)
      return nullptr;
   lastRecordOffset.reset();

   SmallVector<GenericTypeParamDecl *, 8> params;

   ArrayRef<uint64_t> paramIDs;
   GenericParamListLayout::readRecord(scratch, paramIDs);
   for (DeclID nextParamID : paramIDs) {
      auto genericParam = cast<GenericTypeParamDecl>(getDecl(nextParamID));
      params.push_back(genericParam);
   }

   // Don't create empty generic parameter lists. (This should never happen in
   // practice, but it doesn't hurt to be defensive.)
   if (params.empty())
      return nullptr;

   return GenericParamList::create(getContext(), SourceLoc(),
                                   params, SourceLoc(), { },
                                   SourceLoc());
}

void ModuleFile::readGenericRequirements(
   SmallVectorImpl<Requirement> &requirements,
   llvm::BitstreamCursor &Cursor) {
   auto error = readGenericRequirementsChecked(requirements, Cursor);
   if (error)
      fatal(std::move(error));
}

llvm::Error ModuleFile::readGenericRequirementsChecked(
   SmallVectorImpl<Requirement> &requirements,
   llvm::BitstreamCursor &Cursor) {
   using namespace decls_block;

   BCOffsetRAII lastRecordOffset(Cursor);
   SmallVector<uint64_t, 8> scratch;
   StringRef blobData;

   while (true) {
      lastRecordOffset.reset();
      bool shouldContinue = true;

      llvm::BitstreamEntry entry =
         fatalIfUnexpected(Cursor.advance(AF_DontPopBlockAtEnd));
      if (entry.Kind != llvm::BitstreamEntry::Record)
         break;

      scratch.clear();
      unsigned recordID = fatalIfUnexpected(
         Cursor.readRecord(entry.ID, scratch, &blobData));
      switch (recordID) {
         case GENERIC_REQUIREMENT: {
            uint8_t rawKind;
            uint64_t rawTypeIDs[2];
            GenericRequirementLayout::readRecord(scratch, rawKind,
                                                 rawTypeIDs[0], rawTypeIDs[1]);

            switch (rawKind) {
               case GenericRequirementKind::Conformance: {
                  auto subject = getTypeChecked(rawTypeIDs[0]);
                  if (!subject)
                     return subject.takeError();

                  auto constraint = getTypeChecked(rawTypeIDs[1]);
                  if (!constraint)
                     return constraint.takeError();

                  requirements.push_back(Requirement(RequirementKind::Conformance,
                                                     subject.get(), constraint.get()));
                  break;
               }
               case GenericRequirementKind::Superclass: {
                  auto subject = getTypeChecked(rawTypeIDs[0]);
                  if (!subject)
                     return subject.takeError();

                  auto constraint = getTypeChecked(rawTypeIDs[1]);
                  if (!constraint)
                     return constraint.takeError();

                  requirements.push_back(Requirement(RequirementKind::Superclass,
                                                     subject.get(), constraint.get()));
                  break;
               }
               case GenericRequirementKind::SameType: {
                  auto first = getTypeChecked(rawTypeIDs[0]);
                  if (!first)
                     return first.takeError();

                  auto second = getTypeChecked(rawTypeIDs[1]);
                  if (!second)
                     return second.takeError();

                  requirements.push_back(Requirement(RequirementKind::SameType,
                                                     first.get(), second.get()));
                  break;
               }
               default:
                  // Unknown requirement kind.
                  fatal();
            }
            break;
         }
         case LAYOUT_REQUIREMENT: {
            uint8_t rawKind;
            uint64_t rawTypeID;
            uint32_t size;
            uint32_t alignment;
            LayoutRequirementLayout::readRecord(scratch, rawKind, rawTypeID,
                                                size, alignment);

            auto first = getTypeChecked(rawTypeID);
            if (!first)
               return first.takeError();

            LayoutConstraint layout;
            LayoutConstraintKind kind = LayoutConstraintKind::UnknownLayout;
            switch (rawKind) {
               default:
                  // Unknown layout requirement kind.
                  fatal();
               case LayoutRequirementKind::NativeRefCountedObject:
                  kind = LayoutConstraintKind::NativeRefCountedObject;
                  break;
               case LayoutRequirementKind::RefCountedObject:
                  kind = LayoutConstraintKind::RefCountedObject;
                  break;
               case LayoutRequirementKind::Trivial:
                  kind = LayoutConstraintKind::Trivial;
                  break;
               case LayoutRequirementKind::TrivialOfExactSize:
                  kind = LayoutConstraintKind::TrivialOfExactSize;
                  break;
               case LayoutRequirementKind::TrivialOfAtMostSize:
                  kind = LayoutConstraintKind::TrivialOfAtMostSize;
                  break;
               case LayoutRequirementKind::Class:
                  kind = LayoutConstraintKind::Class;
                  break;
               case LayoutRequirementKind::NativeClass:
                  kind = LayoutConstraintKind::NativeClass;
                  break;
               case LayoutRequirementKind::UnknownLayout:
                  kind = LayoutConstraintKind::UnknownLayout;
                  break;
            }

            AstContext &ctx = getContext();
            if (kind != LayoutConstraintKind::TrivialOfAtMostSize &&
                kind != LayoutConstraintKind::TrivialOfExactSize)
               layout = LayoutConstraint::getLayoutConstraint(kind, ctx);
            else
               layout =
                  LayoutConstraint::getLayoutConstraint(kind, size, alignment, ctx);

            requirements.push_back(
               Requirement(RequirementKind::Layout, first.get(), layout));
            break;
         }
         default:
            // This record is not part of the GenericParamList.
            shouldContinue = false;
            break;
      }

      if (!shouldContinue)
         break;
   }

   return llvm::Error::success();
}

/// Advances past any records that might be part of a requirement signature.
static llvm::Error skipGenericRequirements(llvm::BitstreamCursor &Cursor) {
   using namespace decls_block;

   BCOffsetRAII lastRecordOffset(Cursor);

   while (true) {
      Expected<llvm::BitstreamEntry> maybeEntry =
         Cursor.advance(AF_DontPopBlockAtEnd);
      if (!maybeEntry)
         return maybeEntry.takeError();
      llvm::BitstreamEntry entry = maybeEntry.get();
      if (entry.Kind != llvm::BitstreamEntry::Record)
         break;

      Expected<unsigned> maybeRecordID = Cursor.skipRecord(entry.ID);
      if (!maybeRecordID)
         return maybeRecordID.takeError();
      switch (maybeRecordID.get()) {
         case GENERIC_REQUIREMENT:
         case LAYOUT_REQUIREMENT:
            break;

         default:
            // This record is not a generic requirement.
            return llvm::Error::success();
      }

      lastRecordOffset.reset();
   }
   return llvm::Error::success();
}

GenericSignature ModuleFile::getGenericSignature(
   serialization::GenericSignatureID ID) {
   auto signature = getGenericSignatureChecked(ID);
   if (!signature)
      fatal(signature.takeError());
   return signature.get();
}

Expected<GenericSignature>
ModuleFile::getGenericSignatureChecked(serialization::GenericSignatureID ID) {
   using namespace decls_block;

   // Zero is a sentinel for having no generic signature.
   if (ID == 0) return nullptr;

   assert(ID <= GenericSignatures.size() &&
          "invalid GenericSignature ID");
   auto &sigOffset = GenericSignatures[ID-1];

   // If we've already deserialized this generic signature, return it.
   if (sigOffset.isComplete())
      return sigOffset.get();

   // Read the generic signature.
   BCOffsetRAII restoreOffset(DeclTypeCursor);
   fatalIfNotSuccess(DeclTypeCursor.JumpToBit(sigOffset));

   // Read the parameter types.
   SmallVector<GenericTypeParamType *, 4> paramTypes;
   StringRef blobData;
   SmallVector<uint64_t, 8> scratch;

   llvm::BitstreamEntry entry =
      fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
   if (entry.Kind != llvm::BitstreamEntry::Record)
      fatal();

   unsigned recordID = fatalIfUnexpected(
      DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
   switch (recordID) {
      case GENERIC_SIGNATURE: {
         ArrayRef<uint64_t> rawParamIDs;
         GenericSignatureLayout::readRecord(scratch, rawParamIDs);

         for (unsigned i = 0, n = rawParamIDs.size(); i != n; ++i) {
            auto paramTy = getType(rawParamIDs[i])->castTo<GenericTypeParamType>();
            paramTypes.push_back(paramTy);
         }
         break;
      }

      case PIL_GENERIC_SIGNATURE: {
         ArrayRef<uint64_t> rawParamIDs;
         PILGenericSignatureLayout::readRecord(scratch, rawParamIDs);

         if (rawParamIDs.size() % 2 != 0)
            fatal();

         for (unsigned i = 0, n = rawParamIDs.size(); i != n; i += 2) {
            Identifier name = getIdentifier(rawParamIDs[i]);
            auto paramTy = getType(rawParamIDs[i+1])->castTo<GenericTypeParamType>();

            if (!name.empty()) {
               auto paramDecl =
                  createDecl<GenericTypeParamDecl>(getAssociatedModule(),
                                                   name,
                                                   SourceLoc(),
                                                   paramTy->getDepth(),
                                                   paramTy->getIndex());
               paramTy = paramDecl->getDeclaredInterfaceType()
                  ->castTo<GenericTypeParamType>();
            }

            paramTypes.push_back(paramTy);
         }
         break;
      }
      default:
         // Not a generic signature; no way to recover.
         fatal();
   }

   // Read the generic requirements.
   SmallVector<Requirement, 4> requirements;
   auto error = readGenericRequirementsChecked(requirements, DeclTypeCursor);
   if (error)
      return std::move(error);

   // If we've already deserialized this generic signature, start over to return
   // it directly.
   // FIXME: Is this kind of re-entrancy actually possible?
   if (sigOffset.isComplete())
      return getGenericSignature(ID);

   // Construct the generic signature from the loaded parameters and
   // requirements.
   auto signature = GenericSignature::get(paramTypes, requirements);
   sigOffset = signature;
   return signature;
}

SubstitutionMap ModuleFile::getSubstitutionMap(
   serialization::SubstitutionMapID id) {
   auto map = getSubstitutionMapChecked(id);
   if (!map)
      fatal(map.takeError());
   return map.get();
}

Expected<SubstitutionMap>
ModuleFile::getSubstitutionMapChecked(serialization::SubstitutionMapID id) {
   using namespace decls_block;

   // Zero is a sentinel for having an empty substitution map.
   if (id == 0) return SubstitutionMap();

   assert(id <= SubstitutionMaps.size() && "invalid SubstitutionMap ID");
   auto &substitutionsOrOffset = SubstitutionMaps[id-1];

   // If we've already deserialized this substitution map, return it.
   if (substitutionsOrOffset.isComplete()) {
      return substitutionsOrOffset.get();
   }

   // Read the substitution map.
   BCOffsetRAII restoreOffset(DeclTypeCursor);
   fatalIfNotSuccess(DeclTypeCursor.JumpToBit(substitutionsOrOffset));

   // Read the substitution map.
   llvm::BitstreamEntry entry =
      fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
   if (entry.Kind != llvm::BitstreamEntry::Record)
      fatal();

   StringRef blobData;
   SmallVector<uint64_t, 8> scratch;
   unsigned recordID = fatalIfUnexpected(
      DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
   if (recordID != SUBSTITUTION_MAP)
      fatal();

   GenericSignatureID genericSigID;
   uint64_t numConformances;
   ArrayRef<uint64_t> replacementTypeIDs;
   SubstitutionMapLayout::readRecord(scratch, genericSigID, numConformances,
                                     replacementTypeIDs);

   // Generic signature.
   auto genericSigOrError = getGenericSignatureChecked(genericSigID);
   if (!genericSigOrError)
      return genericSigOrError.takeError();

   auto genericSig = genericSigOrError.get();
   if (!genericSig)
      fatal();

   // Load the replacement types.
   SmallVector<Type, 4> replacementTypes;
   replacementTypes.reserve(replacementTypeIDs.size());
   for (auto typeID : replacementTypeIDs) {
      replacementTypes.push_back(getType(typeID));
   }

   // Read the conformances.
   SmallVector<InterfaceConformanceRef, 4> conformances;
   conformances.reserve(numConformances);
   for (unsigned i : range(numConformances)) {
      (void)i;
      conformances.push_back(readConformance(DeclTypeCursor));
   }

   // Form the substitution map and record it.
   auto substitutions =
      SubstitutionMap::get(genericSig, ArrayRef<Type>(replacementTypes),
                           ArrayRef<InterfaceConformanceRef>(conformances));
   substitutionsOrOffset = substitutions;
   return substitutions;
}

bool ModuleFile::readDefaultWitnessTable(InterfaceDecl *proto) {
   using namespace decls_block;

   llvm::BitstreamEntry entry =
      fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
   if (entry.Kind != llvm::BitstreamEntry::Record)
      return true;

   SmallVector<uint64_t, 16> witnessIDBuffer;

   unsigned kind =
      fatalIfUnexpected(DeclTypeCursor.readRecord(entry.ID, witnessIDBuffer));
   assert(kind == DEFAULT_WITNESS_TABLE);
   (void)kind;

   ArrayRef<uint64_t> rawWitnessIDs;
   decls_block::DefaultWitnessTableLayout::readRecord(
      witnessIDBuffer, rawWitnessIDs);

   if (rawWitnessIDs.empty())
      return false;

   unsigned e = rawWitnessIDs.size();
   assert(e % 2 == 0 && "malformed default witness table");
   (void) e;

   for (unsigned i = 0, e = rawWitnessIDs.size(); i < e; i += 2) {
      ValueDecl *requirement = cast<ValueDecl>(getDecl(rawWitnessIDs[i]));
      assert(requirement && "unable to deserialize next requirement");
      ValueDecl *witness = cast<ValueDecl>(getDecl(rawWitnessIDs[i + 1]));
      assert(witness && "unable to deserialize next witness");
      assert(requirement->getDeclContext() == proto);

      proto->setDefaultWitness(requirement, witness);
   }

   return false;
}

static Optional<polar::CtorInitializerKind>
getActualCtorInitializerKind(uint8_t raw) {
   switch (serialization::CtorInitializerKind(raw)) {
#define CASE(NAME) \
  case serialization::CtorInitializerKind::NAME: \
    return polar::CtorInitializerKind::NAME;
      CASE(Designated)
      CASE(Convenience)
      CASE(Factory)
      CASE(ConvenienceFactory)
#undef CASE
   }
   return None;
}

static bool isReExportedToModule(const ValueDecl *value,
                                 const ModuleDecl *expectedModule) {
   const DeclContext *valueDC = value->getDeclContext();
   auto fromClangModule
      = dyn_cast<ClangModuleUnit>(valueDC->getModuleScopeContext());
   if (!fromClangModule)
      return false;
   StringRef exportedName = fromClangModule->getExportedModuleName();

   auto toClangModule
      = dyn_cast<ClangModuleUnit>(expectedModule->getFiles().front());
   if (toClangModule)
      return exportedName == toClangModule->getExportedModuleName();
   return exportedName == expectedModule->getName().str();
}

/// Remove values from \p values that don't match the expected type or module.
///
/// Any of \p expectedTy, \p expectedModule, or \p expectedGenericSig can be
/// omitted, in which case any type or module is accepted. Values imported
/// from Clang can also appear in any module.
static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
                         CanGenericSignature expectedGenericSig, bool isType,
                         bool inInterfaceExt, bool importedFromClang,
                         bool isStatic,
                         Optional<polar::CtorInitializerKind> ctorInit,
                         SmallVectorImpl<ValueDecl *> &values) {
   CanType canTy;
   if (expectedTy)
      canTy = expectedTy->getCanonicalType();

   auto newEnd = std::remove_if(values.begin(), values.end(),
                                [=](ValueDecl *value) {
                                   // Ignore anything that was parsed (vs. deserialized), because a serialized
                                   // module cannot refer to it.
                                   if (value->getDeclContext()->getParentSourceFile())
                                      return true;

                                   if (isType != isa<TypeDecl>(value))
                                      return true;

                                   // If we're expecting a type, make sure this decl has the expected type.
                                   if (canTy && !value->getInterfaceType()->isEqual(canTy))
                                      return true;

                                   if (value->isStatic() != isStatic)
                                      return true;
                                   if (value->hasClangNode() != importedFromClang)
                                      return true;

                                   if (value->getAttrs().hasAttribute<ForbidSerializingReferenceAttr>())
                                      return true;

                                   // FIXME: Should be able to move a value from an extension in a derived
                                   // module to the original definition in a base module.
                                   if (expectedModule && !value->hasClangNode() &&
                                       value->getModuleContext() != expectedModule &&
                                       !isReExportedToModule(value, expectedModule))
                                      return true;

                                   // If we're expecting a member within a constrained extension with a
                                   // particular generic signature, match that signature.
                                   if (expectedGenericSig &&
                                       value->getDeclContext()->getGenericSignatureOfContext()
                                          ->getCanonicalSignature() != expectedGenericSig)
                                      return true;

                                   // If we don't expect a specific generic signature, ignore anything from a
                                   // constrained extension.
                                   if (!expectedGenericSig &&
                                       isa<ExtensionDecl>(value->getDeclContext()) &&
                                       cast<ExtensionDecl>(value->getDeclContext())->isConstrainedExtension())
                                      return true;

                                   // If we're looking at members of a protocol or protocol extension,
                                   // filter by whether we expect to find something in a protocol extension or
                                   // not. This lets us distinguish between a protocol member and a protocol
                                   // extension member that have the same type.
                                   if (value->getDeclContext()->getSelfInterfaceDecl() &&
                                       (bool)value->getDeclContext()->getExtendedInterfaceDecl()
                                       != inInterfaceExt)
                                      return true;

                                   // If we're expecting an initializer with a specific kind, and this is not
                                   // an initializer with that kind, remove it.
                                   if (ctorInit) {
                                      if (!isa<ConstructorDecl>(value) ||
                                          cast<ConstructorDecl>(value)->getInitKind() != *ctorInit)
                                         return true;
                                   }
                                   return false;
                                });
   values.erase(newEnd, values.end());
}

Expected<Decl *>
ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
   using namespace decls_block;

   ModuleDecl *baseModule = getModule(MID);
   if (!baseModule) {
      return llvm::make_error<XRefNonLoadedModuleError>(getIdentifier(MID));
   }

   assert(baseModule && "missing dependency");
   PrettyXRefTrace pathTrace(*baseModule);

   llvm::BitstreamEntry entry =
      fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
   if (entry.Kind != llvm::BitstreamEntry::Record)
      fatal();

   SmallVector<ValueDecl *, 8> values;
   SmallVector<uint64_t, 8> scratch;
   StringRef blobData;

   // Read the first path piece. This one is special because lookup is performed
   // against the base module, rather than against the previous link in the path.
   // In particular, operator path pieces represent actual operators here, but
   // filters on operator functions when they appear later on.
   scratch.clear();
   unsigned recordID = fatalIfUnexpected(
      DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
   switch (recordID) {
      case XREF_TYPE_PATH_PIECE:
      case XREF_VALUE_PATH_PIECE: {
         IdentifierID IID;
         IdentifierID privateDiscriminator = 0;
         TypeID TID = 0;
         bool isType = (recordID == XREF_TYPE_PATH_PIECE);
         bool inInterfaceExt = false;
         bool importedFromClang = false;
         bool isStatic = false;
         if (isType)
            XRefTypePathPieceLayout::readRecord(scratch, IID, privateDiscriminator,
                                                inInterfaceExt, importedFromClang);
         else
            XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inInterfaceExt,
                                                 importedFromClang, isStatic);

         DeclBaseName name = getDeclBaseName(IID);
         pathTrace.addValue(name);
         if (privateDiscriminator)
            pathTrace.addValue(getIdentifier(privateDiscriminator));

         Type filterTy;
         if (!isType) {
            auto maybeType = getTypeChecked(TID);
            if (!maybeType) {
               // FIXME: Don't throw away the inner error's information.
               consumeError(maybeType.takeError());
               return llvm::make_error<XRefError>("couldn't decode type",
                                                  pathTrace, name);
            }
            filterTy = maybeType.get();
            pathTrace.addType(filterTy);
         }

         if (privateDiscriminator) {
            baseModule->lookupMember(values, baseModule, name,
                                     getIdentifier(privateDiscriminator));
         } else {
            baseModule->lookupQualified(baseModule, name,
                                        NL_QualifiedDefault | NL_KnownNoDependency,
                                        values);
         }
         filterValues(filterTy, nullptr, nullptr, isType, inInterfaceExt,
                      importedFromClang, isStatic, None, values);
         break;
      }

      case XREF_OPAQUE_RETURN_TYPE_PATH_PIECE: {
         IdentifierID DefiningDeclNameID;

         XRefOpaqueReturnTypePathPieceLayout::readRecord(scratch, DefiningDeclNameID);

         auto name = getIdentifier(DefiningDeclNameID);
         pathTrace.addOpaqueReturnType(name);

         if (auto opaque = baseModule->lookupOpaqueResultType(name.str())) {
            values.push_back(opaque);
         }
         break;
      }

      case XREF_EXTENSION_PATH_PIECE:
         llvm_unreachable("can only extend a nominal");

      case XREF_OPERATOR_OR_ACCESSOR_PATH_PIECE: {
         IdentifierID IID;
         uint8_t rawOpKind;
         XRefOperatorOrAccessorPathPieceLayout::readRecord(scratch, IID, rawOpKind);

         Identifier opName = getIdentifier(IID);
         pathTrace.addOperator(opName);

         switch (rawOpKind) {
            case OperatorKind::Infix:
               return baseModule->lookupInfixOperator(opName);
            case OperatorKind::Prefix:
               return baseModule->lookupPrefixOperator(opName);
            case OperatorKind::Postfix:
               return baseModule->lookupPostfixOperator(opName);
            case OperatorKind::PrecedenceGroup:
               return baseModule->lookupPrecedenceGroup(opName);
            default:
               // Unknown operator kind.
               fatal();
         }
      }

      case XREF_GENERIC_PARAM_PATH_PIECE:
      case XREF_INITIALIZER_PATH_PIECE:
         llvm_unreachable("only in a nominal or function");

      default:
         // Unknown xref kind.
         pathTrace.addUnknown(recordID);
         fatal();
   }

   auto getXRefDeclNameForError = [&]() -> DeclName {
      DeclName result = pathTrace.getLastName();
      while (--pathLen) {
         llvm::BitstreamEntry entry =
            fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
         if (entry.Kind != llvm::BitstreamEntry::Record)
            return Identifier();

         scratch.clear();
         unsigned recordID = fatalIfUnexpected(
            DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
         switch (recordID) {
            case XREF_TYPE_PATH_PIECE: {
               IdentifierID IID;
               XRefTypePathPieceLayout::readRecord(scratch, IID, None, None, None);
               result = getIdentifier(IID);
               break;
            }
            case XREF_VALUE_PATH_PIECE: {
               IdentifierID IID;
               XRefValuePathPieceLayout::readRecord(scratch, None, IID, None, None,
                                                    None);
               result = getIdentifier(IID);
               break;
            }
            case XREF_OPAQUE_RETURN_TYPE_PATH_PIECE: {
               IdentifierID IID;
               XRefOpaqueReturnTypePathPieceLayout::readRecord(scratch, IID);
               auto mangledName = getIdentifier(IID);

               SmallString<64> buf;
               {
                  llvm::raw_svector_ostream os(buf);
                  os << "<<opaque return type of ";
                  os << mangledName.str();
                  os << ">>";
               }

               result = getContext().getIdentifier(buf);
               break;
            }
            case XREF_INITIALIZER_PATH_PIECE:
               result = DeclBaseName::createConstructor();
               break;

            case XREF_EXTENSION_PATH_PIECE:
            case XREF_OPERATOR_OR_ACCESSOR_PATH_PIECE:
               break;

            case XREF_GENERIC_PARAM_PATH_PIECE:
               // Can't get the name without deserializing.
               result = Identifier();
               break;

            default:
               // Unknown encoding.
               return Identifier();
         }
      }
      return result;
   };

   if (values.empty()) {
      return llvm::make_error<XRefError>("top-level value not found", pathTrace,
                                         getXRefDeclNameForError());
   }

   // Filters for values discovered in the remaining path pieces.
   ModuleDecl *M = nullptr;
   CanGenericSignature genericSig = CanGenericSignature();

   // For remaining path pieces, filter or drill down into the results we have.
   while (--pathLen) {
      llvm::BitstreamEntry entry =
         fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
      if (entry.Kind != llvm::BitstreamEntry::Record)
         fatal();

      scratch.clear();
      unsigned recordID = fatalIfUnexpected(
         DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
      switch (recordID) {
         case XREF_TYPE_PATH_PIECE: {
            if (values.size() == 1 && isa<NominalTypeDecl>(values.front())) {
               // Fast path for nested types that avoids deserializing all
               // members of the parent type.
               IdentifierID IID;
               IdentifierID privateDiscriminator;
               bool importedFromClang = false;
               bool inInterfaceExt = false;
               XRefTypePathPieceLayout::readRecord(scratch, IID, privateDiscriminator,
                                                   inInterfaceExt, importedFromClang);
               if (privateDiscriminator)
                  goto giveUpFastPath;

               Identifier memberName = getIdentifier(IID);
               pathTrace.addValue(memberName);

               llvm::PrettyStackTraceString message{
                  "If you're seeing a crash here, try passing "
                  "-Xfrontend -disable-serialization-nested-type-lookup-table"};

               auto *baseType = cast<NominalTypeDecl>(values.front());
               ModuleDecl *extensionModule = M;
               if (!extensionModule)
                  extensionModule = baseType->getModuleContext();

               // Fault in extensions, then ask every file in the module.
               (void)baseType->getExtensions();
               TypeDecl *nestedType = nullptr;
               for (FileUnit *file : extensionModule->getFiles()) {
                  if (file == getFile())
                     continue;
                  nestedType = file->lookupNestedType(memberName, baseType);
                  if (nestedType)
                     break;
               }

               if (nestedType) {
                  SmallVector<ValueDecl *, 1> singleValueBuffer{nestedType};
                  filterValues(/*expectedTy*/Type(), extensionModule, genericSig,
                     /*isType*/true, inInterfaceExt, importedFromClang,
                     /*isStatic*/false, /*ctorInit*/None, singleValueBuffer);
                  if (!singleValueBuffer.empty()) {
                     values.assign({nestedType});
                     ++NumNestedTypeShortcuts;
                     break;
                  }
               }

               pathTrace.removeLast();
            }
giveUpFastPath:
            LLVM_FALLTHROUGH;
         }
         case XREF_VALUE_PATH_PIECE:
         case XREF_INITIALIZER_PATH_PIECE: {
            TypeID TID = 0;
            DeclBaseName memberName;
            Identifier privateDiscriminator;
            Optional<polar::CtorInitializerKind> ctorInit;
            bool isType = false;
            bool inInterfaceExt = false;
            bool importedFromClang = false;
            bool isStatic = false;
            switch (recordID) {
               case XREF_TYPE_PATH_PIECE: {
                  IdentifierID IID, discriminatorID;
                  XRefTypePathPieceLayout::readRecord(scratch, IID, discriminatorID,
                                                      inInterfaceExt, importedFromClang);
                  memberName = getDeclBaseName(IID);
                  privateDiscriminator = getIdentifier(discriminatorID);
                  isType = true;
                  break;
               }

               case XREF_VALUE_PATH_PIECE: {
                  IdentifierID IID;
                  XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inInterfaceExt,
                                                       importedFromClang, isStatic);
                  memberName = getDeclBaseName(IID);
                  break;
               }

               case XREF_INITIALIZER_PATH_PIECE: {
                  uint8_t kind;
                  XRefInitializerPathPieceLayout::readRecord(scratch, TID, inInterfaceExt,
                                                             importedFromClang, kind);
                  memberName = DeclBaseName::createConstructor();
                  ctorInit = getActualCtorInitializerKind(kind);
                  break;
               }

               default:
                  llvm_unreachable("Unhandled path piece");
            }

            pathTrace.addValue(memberName);
            if (!privateDiscriminator.empty())
               pathTrace.addPrivateDiscriminator(privateDiscriminator);

            Type filterTy;
            if (!isType) {
               auto maybeType = getTypeChecked(TID);
               if (!maybeType) {
                  // FIXME: Don't throw away the inner error's information.
                  consumeError(maybeType.takeError());
                  return llvm::make_error<XRefError>("couldn't decode type",
                                                     pathTrace, memberName);
               }
               filterTy = maybeType.get();
               pathTrace.addType(filterTy);
            }

            if (values.size() != 1) {
               return llvm::make_error<XRefError>("multiple matching base values",
                                                  pathTrace,
                                                  getXRefDeclNameForError());
            }

            auto nominal = dyn_cast<NominalTypeDecl>(values.front());
            values.clear();

            if (!nominal) {
               return llvm::make_error<XRefError>("base is not a nominal type",
                                                  pathTrace,
                                                  getXRefDeclNameForError());
            }

            if (!privateDiscriminator.empty()) {
               ModuleDecl *searchModule = M;
               if (!searchModule)
                  searchModule = nominal->getModuleContext();
               searchModule->lookupMember(values, nominal, memberName,
                                          privateDiscriminator);

            } else {
               auto members = nominal->lookupDirect(memberName);
               values.append(members.begin(), members.end());
            }
            filterValues(filterTy, M, genericSig, isType, inInterfaceExt,
                         importedFromClang, isStatic, ctorInit, values);
            break;
         }

         case XREF_EXTENSION_PATH_PIECE: {
            ModuleID ownerID;
            GenericSignatureID rawGenericSig;
            XRefExtensionPathPieceLayout::readRecord(scratch, ownerID, rawGenericSig);
            M = getModule(ownerID);
            if (!M) {
               return llvm::make_error<XRefError>("module is not loaded",
                                                  pathTrace, getIdentifier(ownerID));
            }
            pathTrace.addExtension(M);

            // Read the generic signature, if we have one.
            genericSig = CanGenericSignature(getGenericSignature(rawGenericSig));

            continue;
         }

         case XREF_OPERATOR_OR_ACCESSOR_PATH_PIECE: {
            uint8_t rawKind;
            XRefOperatorOrAccessorPathPieceLayout::readRecord(scratch, None,
                                                              rawKind);
            if (values.empty())
               break;

            if (!values.front()->getBaseName().isOperator()) {
               pathTrace.addAccessor(rawKind);
               if (auto storage = dyn_cast<AbstractStorageDecl>(values.front())) {
                  auto actualKind = getActualAccessorKind(rawKind);
                  if (!actualKind) {
                     // Unknown accessor kind.
                     fatal();
                  }
                  values.front() = storage->getAccessor(*actualKind);
                  if (!values.front()) {
                     return llvm::make_error<XRefError>("missing accessor",
                                                        pathTrace,
                                                        getXRefDeclNameForError());

                  }
               }
               break;
            }

            pathTrace.addOperatorFilter(rawKind);

            auto newEnd = std::remove_if(values.begin(), values.end(),
                                         [=](ValueDecl *value) {
                                            auto fn = dyn_cast<FuncDecl>(value);
                                            if (!fn)
                                               return true;
                                            if (!fn->getOperatorDecl())
                                               return true;
                                            if (getStableFixity(fn->getOperatorDecl()->getKind()) != rawKind)
                                               return true;
                                            return false;
                                         });
            values.erase(newEnd, values.end());
            break;
         }

         case XREF_GENERIC_PARAM_PATH_PIECE: {
            if (values.size() != 1) {
               return llvm::make_error<XRefError>("multiple matching base values",
                                                  pathTrace,
                                                  getXRefDeclNameForError());
            }

            uint32_t depth, paramIndex;
            XRefGenericParamPathPieceLayout::readRecord(scratch, depth, paramIndex);

            pathTrace.addGenericParam(paramIndex);

            ValueDecl *base = values.front();

            GenericSignature currentSig = GenericSignature();
            if (auto nominal = dyn_cast<NominalTypeDecl>(base)) {
               if (genericSig) {
                  // Find an extension in the requested module that has the
                  // correct generic signature.
                  for (auto ext : nominal->getExtensions()) {
                     if (ext->getModuleContext() == M &&
                         ext->getGenericSignature()->getCanonicalSignature()
                         == genericSig) {
                        currentSig = ext->getGenericSignature();
                        break;
                     }
                  }
                  assert(currentSig && "Couldn't find constrained extension");
               } else {
                  // Simple case: use the nominal type's generic parameters.
                  currentSig = nominal->getGenericSignature();
               }
            } else if (auto alias = dyn_cast<TypeAliasDecl>(base)) {
               currentSig = alias->getGenericSignature();
            } else if (auto fn = dyn_cast<AbstractFunctionDecl>(base)) {
               currentSig = fn->getGenericSignature();
            } else if (auto subscript = dyn_cast<SubscriptDecl>(base)) {
               currentSig = subscript->getGenericSignature();
            } else if (auto opaque = dyn_cast<OpaqueTypeDecl>(base)) {
               currentSig = opaque->getGenericSignature();
            }

            if (!currentSig) {
               return llvm::make_error<XRefError>(
                  "cross-reference to generic param for non-generic type",
                  pathTrace, getXRefDeclNameForError());
            }

            bool found = false;
            for (auto paramTy : currentSig->getGenericParams()) {
               if (paramTy->getIndex() == paramIndex &&
                   paramTy->getDepth() == depth) {
                  values.clear();
                  values.push_back(paramTy->getDecl());
                  found = true;
                  break;
               }
            }

            if (!found) {
               return llvm::make_error<XRefError>(
                  "invalid generic argument index or depth",
                  pathTrace, getXRefDeclNameForError());
            }

            break;
         }

         case XREF_OPAQUE_RETURN_TYPE_PATH_PIECE: {
            values.clear();
            IdentifierID DefiningDeclNameID;

            XRefOpaqueReturnTypePathPieceLayout::readRecord(scratch, DefiningDeclNameID);

            auto name = getIdentifier(DefiningDeclNameID);
            pathTrace.addOpaqueReturnType(name);

            auto lookupModule = M ? M : baseModule;
            if (auto opaqueTy = lookupModule->lookupOpaqueResultType(name.str())) {
               values.push_back(opaqueTy);
            }
            break;
         }

         default:
            // Unknown xref path piece.
            pathTrace.addUnknown(recordID);
            fatal();
      }

      Optional<PrettyStackTraceModuleFile> traceMsg;
      if (M != getAssociatedModule()) {
         traceMsg.emplace("If you're seeing a crash here, check that your SDK "
                          "and dependencies match the versions used to build",
                          *this);
      }

      if (values.empty()) {
         return llvm::make_error<XRefError>("result not found", pathTrace,
                                            getXRefDeclNameForError());
      }

      // Reset the module filter.
      M = nullptr;
      genericSig = nullptr;
   }

   // Make sure we /used/ the last module filter we got.
   // This catches the case where the last path piece we saw was an Extension
   // path piece, which is not a valid way to end a path. (Cross-references to
   // extensions are not allowed because they cannot be uniquely named.)
   if (M)
      fatal();

   // When all is said and done, we should have a single value here to return.
   if (values.size() != 1) {
      return llvm::make_error<XRefError>("result is ambiguous", pathTrace,
                                         getXRefDeclNameForError());
   }

   assert(values.front() != nullptr);
   return values.front();
}

DeclBaseName ModuleFile::getDeclBaseName(IdentifierID IID) {
   if (IID == 0)
      return Identifier();

   if (IID < NUM_SPECIAL_IDS) {
      switch (static_cast<SpecialIdentifierID>(static_cast<uint8_t>(IID))) {
         case BUILTIN_MODULE_ID:
         case CURRENT_MODULE_ID:
         case OBJC_HEADER_MODULE_ID:
            llvm_unreachable("Cannot get DeclBaseName of special module id");
         case SUBSCRIPT_ID:
            return DeclBaseName::createSubscript();
         case serialization::CONSTRUCTOR_ID:
            return DeclBaseName::createConstructor();
         case serialization::DESTRUCTOR_ID:
            return DeclBaseName::createDestructor();
         case NUM_SPECIAL_IDS:
            llvm_unreachable("implementation detail only");
      }
   }

   size_t rawID = IID - NUM_SPECIAL_IDS;
   assert(rawID < Identifiers.size() && "invalid identifier ID");
   auto &identRecord = Identifiers[rawID];

   if (identRecord.Ident.empty()) {
      StringRef text = getIdentifierText(IID);
      identRecord.Ident = getContext().getIdentifier(text);
   }
   return identRecord.Ident;
}

Identifier ModuleFile::getIdentifier(IdentifierID IID) {
   auto name = getDeclBaseName(IID);
   assert(!name.isSpecial());
   return name.getIdentifier();
}

StringRef ModuleFile::getIdentifierText(IdentifierID IID) {
   if (IID == 0)
      return StringRef();

   assert(IID >= NUM_SPECIAL_IDS);

   size_t rawID = IID - NUM_SPECIAL_IDS;
   assert(rawID < Identifiers.size() && "invalid identifier ID");
   auto identRecord = Identifiers[rawID];

   if (!identRecord.Ident.empty())
      return identRecord.Ident.str();

   assert(!IdentifierData.empty() && "no identifier data in module");

   StringRef rawStrPtr = IdentifierData.substr(identRecord.Offset);
   size_t terminatorOffset = rawStrPtr.find('\0');
   assert(terminatorOffset != StringRef::npos &&
          "unterminated identifier string data");
   return rawStrPtr.slice(0, terminatorOffset);
}

DeclContext *ModuleFile::getLocalDeclContext(LocalDeclContextID DCID) {
   assert(DCID != 0 && "invalid local DeclContext ID 0");
   auto &declContextOrOffset = LocalDeclContexts[DCID-1];

   if (declContextOrOffset.isComplete())
      return declContextOrOffset;

   BCOffsetRAII restoreOffset(DeclTypeCursor);
   fatalIfNotSuccess(DeclTypeCursor.JumpToBit(declContextOrOffset));
   llvm::BitstreamEntry entry = fatalIfUnexpected(DeclTypeCursor.advance());

   if (entry.Kind != llvm::BitstreamEntry::Record)
      fatal();

   AstContext &ctx = getContext();
   SmallVector<uint64_t, 64> scratch;
   StringRef blobData;

   unsigned recordID = fatalIfUnexpected(
      DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
   switch(recordID) {
      case decls_block::ABSTRACT_CLOSURE_EXPR_CONTEXT: {
         TypeID closureTypeID;
         unsigned discriminator = 0;
         bool implicit = false;
         DeclContextID parentID;

         decls_block::AbstractClosureExprLayout::readRecord(scratch,
                                                            closureTypeID,
                                                            implicit,
                                                            discriminator,
                                                            parentID);
         DeclContext *parent = getDeclContext(parentID);
         auto type = getType(closureTypeID);

         declContextOrOffset = new (ctx)
            SerializedAbstractClosureExpr(type, implicit, discriminator, parent);
         break;
      }

      case decls_block::TOP_LEVEL_CODE_DECL_CONTEXT: {
         DeclContextID parentID;
         decls_block::TopLevelCodeDeclContextLayout::readRecord(scratch,
                                                                parentID);
         DeclContext *parent = getDeclContext(parentID);

         declContextOrOffset = new (ctx) SerializedTopLevelCodeDeclContext(parent);
         break;
      }

      case decls_block::PATTERN_BINDING_INITIALIZER_CONTEXT: {
         DeclID bindingID;
         uint32_t bindingIndex;
         decls_block::PatternBindingInitializerLayout::readRecord(scratch,
                                                                  bindingID,
                                                                  bindingIndex);
         auto decl = getDecl(bindingID);
         PatternBindingDecl *binding = cast<PatternBindingDecl>(decl);

         if (!declContextOrOffset.isComplete())
            declContextOrOffset = new (ctx)
               SerializedPatternBindingInitializer(binding, bindingIndex);

         if (!blobData.empty())
            binding->setInitStringRepresentation(bindingIndex, blobData);
         break;
      }

      case decls_block::DEFAULT_ARGUMENT_INITIALIZER_CONTEXT: {
         DeclContextID parentID;
         unsigned index = 0;
         decls_block::DefaultArgumentInitializerLayout::readRecord(scratch,
                                                                   parentID,
                                                                   index);
         DeclContext *parent = getDeclContext(parentID);

         declContextOrOffset = new (ctx)
            SerializedDefaultArgumentInitializer(index, parent);
         break;
      }

      default:
         llvm_unreachable("Unknown record ID found when reading local DeclContext.");
   }
   return declContextOrOffset;
}

DeclContext *ModuleFile::getDeclContext(DeclContextID DCID) {
   if (!DCID)
      return FileContext;

   if (Optional<LocalDeclContextID> contextID = DCID.getAsLocalDeclContextID())
      return getLocalDeclContext(contextID.getValue());

   auto D = getDecl(DCID.getAsDeclID().getValue());

   if (auto GTD = dyn_cast<GenericTypeDecl>(D))
      return GTD;
   if (auto ED = dyn_cast<ExtensionDecl>(D))
      return ED;
   if (auto AFD = dyn_cast<AbstractFunctionDecl>(D))
      return AFD;
   if (auto SD = dyn_cast<SubscriptDecl>(D))
      return SD;
   if (auto EED = dyn_cast<EnumElementDecl>(D))
      return EED;

   llvm_unreachable("Unknown Decl : DeclContext kind");
}

ModuleDecl *ModuleFile::getModule(ModuleID MID) {
   if (MID < NUM_SPECIAL_IDS) {
      switch (static_cast<SpecialIdentifierID>(static_cast<uint8_t>(MID))) {
         case BUILTIN_MODULE_ID:
            return getContext().TheBuiltinModule;
         case CURRENT_MODULE_ID:
            return FileContext->getParentModule();
         case OBJC_HEADER_MODULE_ID: {
            auto clangImporter =
               static_cast<ClangImporter *>(getContext().getClangModuleLoader());
            return clangImporter->getImportedHeaderModule();
         }
         case SUBSCRIPT_ID:
         case CONSTRUCTOR_ID:
         case DESTRUCTOR_ID:
            llvm_unreachable("Modules cannot be named with special names");
         case NUM_SPECIAL_IDS:
            llvm_unreachable("implementation detail only");
      }
   }
   return getModule(getIdentifier(MID));
}

ModuleDecl *ModuleFile::getModule(ArrayRef<Identifier> name,
                                  bool allowLoading) {
   if (name.empty() || name.front().empty())
      return getContext().TheBuiltinModule;

   // FIXME: duplicated from NameBinder::getModule
   if (name.size() == 1 &&
       name.front() == FileContext->getParentModule()->getName()) {
      if (!UnderlyingModule && allowLoading) {
         auto importer = getContext().getClangModuleLoader();
         assert(importer && "no way to import shadowed module");
         UnderlyingModule = importer->loadModule(SourceLoc(),
                                                 {{name.front(), SourceLoc()}});
      }

      return UnderlyingModule;
   }

   SmallVector<ImportDecl::AccessPathElement, 4> importPath;
   for (auto pathElem : name)
      importPath.push_back({ pathElem, SourceLoc() });

   if (allowLoading)
      return getContext().getModule(importPath);
   return getContext().getLoadedModule(importPath);
}


/// Translate from the Serialization associativity enum values to the AST
/// strongly-typed enum.
///
/// The former is guaranteed to be stable, but may not reflect this version of
/// the AST.
static Optional<polar::Associativity> getActualAssociativity(uint8_t assoc) {
   switch (assoc) {
      case serialization::Associativity::LeftAssociative:
         return polar::Associativity::Left;
      case serialization::Associativity::RightAssociative:
         return polar::Associativity::Right;
      case serialization::Associativity::NonAssociative:
         return polar::Associativity::None;
      default:
         return None;
   }
}

static Optional<polar::StaticSpellingKind>
getActualStaticSpellingKind(uint8_t raw) {
   switch (serialization::StaticSpellingKind(raw)) {
      case serialization::StaticSpellingKind::None:
         return polar::StaticSpellingKind::None;
      case serialization::StaticSpellingKind::KeywordStatic:
         return polar::StaticSpellingKind::KeywordStatic;
      case serialization::StaticSpellingKind::KeywordClass:
         return polar::StaticSpellingKind::KeywordClass;
   }
   return None;
}

static bool isDeclAttrRecord(unsigned ID) {
   using namespace decls_block;
   switch (ID) {
#define DECL_ATTR(NAME, CLASS, ...) case CLASS##_DECL_ATTR: return true;
#include "polarphp/serialization/internal/DeclTypeRecordNodesDef.h"
      default: return false;
   }
}

static Optional<polar::AccessLevel> getActualAccessLevel(uint8_t raw) {
   switch (serialization::AccessLevel(raw)) {
#define CASE(NAME) \
  case serialization::AccessLevel::NAME: \
    return polar::AccessLevel::NAME;
      CASE(Private)
      CASE(FilePrivate)
      CASE(Internal)
      CASE(Public)
      CASE(Open)
#undef CASE
   }
   return None;
}

static Optional<polar::SelfAccessKind>
getActualSelfAccessKind(uint8_t raw) {
   switch (serialization::SelfAccessKind(raw)) {
      case serialization::SelfAccessKind::NonMutating:
         return polar::SelfAccessKind::NonMutating;
      case serialization::SelfAccessKind::Mutating:
         return polar::SelfAccessKind::Mutating;
      case serialization::SelfAccessKind::Consuming:
         return polar::SelfAccessKind::Consuming;
   }
   return None;
}

/// Translate from the serialization VarDeclSpecifier enumerators, which are
/// guaranteed to be stable, to the AST ones.
static Optional<polar::ParamDecl::Specifier>
getActualParamDeclSpecifier(serialization::ParamDeclSpecifier raw) {
   switch (raw) {
#define CASE(ID) \
  case serialization::ParamDeclSpecifier::ID: \
    return polar::ParamDecl::Specifier::ID;
      CASE(Default)
      CASE(InOut)
      CASE(Shared)
      CASE(Owned)
   }
#undef CASE
   return None;
}

static Optional<polar::VarDecl::Introducer>
getActualVarDeclIntroducer(serialization::VarDeclIntroducer raw) {
   switch (raw) {
#define CASE(ID) \
  case serialization::VarDeclIntroducer::ID: \
    return polar::VarDecl::Introducer::ID;
      CASE(Let)
      CASE(Var)
   }
#undef CASE
   return None;
}

static Optional<polar::OpaqueReadOwnership>
getActualOpaqueReadOwnership(unsigned rawKind) {
   switch (serialization::OpaqueReadOwnership(rawKind)) {
#define CASE(KIND)                               \
  case serialization::OpaqueReadOwnership::KIND: \
    return polar::OpaqueReadOwnership::KIND;
      CASE(Owned)
      CASE(Borrowed)
      CASE(OwnedOrBorrowed)
#undef CASE
   }
   return None;
}

static Optional<polar::ReadImplKind>
getActualReadImplKind(unsigned rawKind) {
   switch (serialization::ReadImplKind(rawKind)) {
#define CASE(KIND)                        \
  case serialization::ReadImplKind::KIND: \
    return polar::ReadImplKind::KIND;
      CASE(Stored)
      CASE(Get)
      CASE(Inherited)
      CASE(Address)
      CASE(Read)
#undef CASE
   }
   return None;
}

static Optional<polar::WriteImplKind>
getActualWriteImplKind(unsigned rawKind) {
   switch (serialization::WriteImplKind(rawKind)) {
#define CASE(KIND)                         \
  case serialization::WriteImplKind::KIND: \
    return polar::WriteImplKind::KIND;
      CASE(Immutable)
      CASE(Stored)
      CASE(Set)
      CASE(StoredWithObservers)
      CASE(InheritedWithObservers)
      CASE(MutableAddress)
      CASE(Modify)
#undef CASE
   }
   return None;
}

static Optional<polar::ReadWriteImplKind>
getActualReadWriteImplKind(unsigned rawKind) {
   switch (serialization::ReadWriteImplKind(rawKind)) {
#define CASE(KIND)                             \
  case serialization::ReadWriteImplKind::KIND: \
    return polar::ReadWriteImplKind::KIND;
      CASE(Immutable)
      CASE(Stored)
      CASE(MutableAddress)
      CASE(MaterializeToTemporary)
      CASE(Modify)
#undef CASE
   }
   return None;
}

void ModuleFile::configureStorage(AbstractStorageDecl *decl,
                                  uint8_t rawOpaqueReadOwnership,
                                  uint8_t rawReadImplKind,
                                  uint8_t rawWriteImplKind,
                                  uint8_t rawReadWriteImplKind,
                                  AccessorRecord &rawIDs) {
   auto opaqueReadOwnership =
      getActualOpaqueReadOwnership(rawOpaqueReadOwnership);
   if (!opaqueReadOwnership)
      return;
   decl->setOpaqueReadOwnership(*opaqueReadOwnership);

   auto readImpl = getActualReadImplKind(rawReadImplKind);
   if (!readImpl) return;

   auto writeImpl = getActualWriteImplKind(rawWriteImplKind);
   if (!writeImpl) return;

   auto readWriteImpl = getActualReadWriteImplKind(rawReadWriteImplKind);
   if (!readWriteImpl) return;

   SmallVector<AccessorDecl*, 8> accessors;
   for (DeclID id : rawIDs.IDs) {
      auto accessor = dyn_cast_or_null<AccessorDecl>(getDecl(id));
      if (!accessor) return;
      accessors.push_back(accessor);
   }

   auto implInfo = StorageImplInfo(*readImpl, *writeImpl, *readWriteImpl);
   decl->setImplInfo(implInfo);

   if (implInfo.isSimpleStored() && accessors.empty())
      return;

   // We currently don't serialize these locations.
   SourceLoc beginLoc, endLoc;

   decl->setAccessors(beginLoc, accessors, endLoc);
}

template <typename T, typename ...Args>
T *ModuleFile::createDecl(Args &&... args) {
   // Note that this method is not used for all decl kinds.
   static_assert(std::is_base_of<Decl, T>::value, "not a Decl");
   return new (getContext()) T(std::forward<Args>(args)...);
}

static const uint64_t lazyConformanceContextDataPositionMask = 0xFFFFFFFFFFFF;

/// Decode the context data for lazily-loaded conformances.
static std::pair<uint64_t, uint64_t> decodeLazyConformanceContextData(
   uint64_t contextData) {
   return std::make_pair(contextData >> 48,
                         contextData & lazyConformanceContextDataPositionMask);
}

/// Encode the context data for lazily-loaded conformances.
static uint64_t encodeLazyConformanceContextData(uint64_t numInterfaces,
                                                 uint64_t bitPosition) {
   assert(numInterfaces < 0xFFFF);
   assert(bitPosition < lazyConformanceContextDataPositionMask);
   return (numInterfaces << 48) | bitPosition;
}

template <typename DERIVED>
static bool attributeChainContains(DeclAttribute *attr) {
   DeclAttributes tempAttrs;
   tempAttrs.setRawAttributeChain(attr);
   static_assert(std::is_trivially_destructible<DeclAttributes>::value,
                 "must not try to destroy the attribute chain");
   return tempAttrs.hasAttribute<DERIVED>();
}

Decl *ModuleFile::getDecl(DeclID DID) {
   Expected<Decl *> deserialized = getDeclChecked(DID);
   if (!deserialized) {
      fatal(deserialized.takeError());
   }
   return deserialized.get();
}

/// Used to split up methods that would otherwise live in ModuleFile.
class polar::DeclDeserializer {
   template <typename T>
   using Serialized = ModuleFile::Serialized<T>;
   using TypeID = serialization::TypeID;

   ModuleFile &MF;
   AstContext &ctx;
   Serialized<Decl *> &declOrOffset;

   DeclAttribute *DAttrs = nullptr;
   DeclAttribute **AttrsNext = &DAttrs;

   Identifier privateDiscriminator;
   unsigned localDiscriminator = 0;
   StringRef filenameForPrivate;

   void AddAttribute(DeclAttribute *Attr) {
      // Advance the linked list.
      // This isn't just using DeclAttributes because that would result in the
      // attributes getting reversed.
      // FIXME: If we reverse them at serialization time we could get rid of this.
      *AttrsNext = Attr;
      AttrsNext = Attr->getMutableNext();
   };

   void handleInherited(llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
                        ArrayRef<uint64_t> rawInheritedIDs) {
      SmallVector<TypeLoc, 2> inheritedTypes;
      for (auto rawID : rawInheritedIDs) {
         auto maybeType = MF.getTypeChecked(rawID);
         if (!maybeType) {
            llvm::consumeError(maybeType.takeError());
            continue;
         }
         inheritedTypes.push_back(TypeLoc::withoutLoc(MF.getType(rawID)));
      }

      auto inherited = ctx.AllocateCopy(inheritedTypes);
      if (auto *typeDecl = decl.dyn_cast<TypeDecl *>())
         typeDecl->setInherited(inherited);
      else
         decl.get<ExtensionDecl *>()->setInherited(inherited);
   }

public:
   DeclDeserializer(ModuleFile &MF, Serialized<Decl *> &declOrOffset)
      : MF(MF), ctx(MF.getContext()), declOrOffset(declOrOffset) {}

   ~DeclDeserializer() {
      if (!declOrOffset.isComplete()) {
         // We failed to deserialize this declaration.
         return;
      }

      Decl *decl = declOrOffset.get();
      if (!decl)
         return;

      if (DAttrs)
         decl->getAttrs().setRawAttributeChain(DAttrs);

      if (auto value = dyn_cast<ValueDecl>(decl)) {
         if (!privateDiscriminator.empty())
            MF.PrivateDiscriminatorsByValue[value] = privateDiscriminator;

         if (localDiscriminator != 0)
            value->setLocalDiscriminator(localDiscriminator);

         if (!filenameForPrivate.empty())
            MF.FilenamesForPrivateValues[value] = filenameForPrivate;
      }
   }

   /// Deserializes decl attribute and attribute-like records from
   /// \c MF.DeclTypesCursor until a non-attribute record is found,
   /// passing each one to AddAttribute.
   llvm::Error deserializeDeclAttributes();

   Expected<Decl *> getDeclCheckedImpl(
      llvm::function_ref<bool(DeclAttributes)> matchAttributes = nullptr);

   Expected<Decl *> deserializeTypeAlias(ArrayRef<uint64_t> scratch,
                                         StringRef blobData) {
      IdentifierID nameID;
      DeclContextID contextID;
      TypeID underlyingTypeID, interfaceTypeID;
      bool isImplicit;
      GenericSignatureID genericSigID;
      uint8_t rawAccessLevel;
      ArrayRef<uint64_t> dependencyIDs;

      decls_block::TypeAliasLayout::readRecord(scratch, nameID, contextID,
                                               underlyingTypeID, interfaceTypeID,
                                               isImplicit, genericSigID,
                                               rawAccessLevel, dependencyIDs);

      Identifier name = MF.getIdentifier(nameID);

      for (TypeID dependencyID : dependencyIDs) {
         auto dependency = MF.getTypeChecked(dependencyID);
         if (!dependency) {
            return llvm::make_error<TypeError>(
               name, takeErrorInfo(dependency.takeError()));
         }
      }

      auto DC = MF.getDeclContext(contextID);

      auto genericParams = MF.maybeReadGenericParams(DC);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto alias = MF.createDecl<TypeAliasDecl>(SourceLoc(), SourceLoc(), name,
                                                SourceLoc(), genericParams, DC);
      declOrOffset = alias;

      auto genericSig = MF.getGenericSignature(genericSigID);
      alias->setGenericSignature(genericSig);

      auto underlying = MF.getType(underlyingTypeID);
      alias->setUnderlyingType(underlying);

      if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
         alias->setAccess(*accessLevel);
      else
         MF.fatal();

      if (isImplicit)
         alias->setImplicit();

      return alias;
   }

   Expected<Decl *>
   deserializeGenericTypeParamDecl(ArrayRef<uint64_t> scratch,
                                   StringRef blobData) {
      IdentifierID nameID;
      bool isImplicit;
      unsigned depth;
      unsigned index;

      decls_block::GenericTypeParamDeclLayout::readRecord(scratch, nameID,
                                                          isImplicit,
                                                          depth,
                                                          index);

      // Always create GenericTypeParamDecls in the associated module;
      // the real context will reparent them.
      auto DC = MF.getAssociatedModule();
      auto genericParam = MF.createDecl<GenericTypeParamDecl>(
         DC, MF.getIdentifier(nameID), SourceLoc(), depth, index);
      declOrOffset = genericParam;

      if (isImplicit)
         genericParam->setImplicit();

      return genericParam;
   }

   Expected<Decl *>
   deserializeAssociatedTypeDecl(ArrayRef<uint64_t> scratch,
                                 StringRef blobData) {
      IdentifierID nameID;
      DeclContextID contextID;
      TypeID defaultDefinitionID;
      bool isImplicit;
      ArrayRef<uint64_t> rawOverriddenIDs;

      decls_block::AssociatedTypeDeclLayout::readRecord(scratch, nameID,
                                                        contextID,
                                                        defaultDefinitionID,
                                                        isImplicit,
                                                        rawOverriddenIDs);

      auto DC = MF.getDeclContext(contextID);
      if (declOrOffset.isComplete())
         return declOrOffset;

      // The where-clause information is pushed up into the protocol
      // (specifically, into its requirement signature) and
      // serialized/deserialized there, so the actual Decl doesn't need to store
      // it.
      TrailingWhereClause *trailingWhere = nullptr;
      auto assocType = MF.createDecl<AssociatedTypeDecl>(
         DC, SourceLoc(), MF.getIdentifier(nameID), SourceLoc(), trailingWhere,
         &MF, defaultDefinitionID);
      declOrOffset = assocType;

      assert(!assocType->getDeclaredInterfaceType()->hasError() &&
             "erroneous associated type");

      AccessLevel parentAccess = cast<InterfaceDecl>(DC)->getFormalAccess();
      assocType->setAccess(std::max(parentAccess, AccessLevel::Internal));
      if (isImplicit)
         assocType->setImplicit();

      // Overridden associated types.
      SmallVector<ValueDecl *, 2> overriddenAssocTypes;
      for (auto overriddenID : rawOverriddenIDs) {
         if (auto overriddenAssocType =
            dyn_cast_or_null<AssociatedTypeDecl>(MF.getDecl(overriddenID))) {
            overriddenAssocTypes.push_back(overriddenAssocType);
         }
      }
      assocType->setOverriddenDecls(overriddenAssocTypes);

      return assocType;
   }

   Expected<Decl *> deserializeStruct(ArrayRef<uint64_t> scratch,
                                      StringRef blobData) {
      IdentifierID nameID;
      DeclContextID contextID;
      bool isImplicit;
      bool isObjC;
      GenericSignatureID genericSigID;
      uint8_t rawAccessLevel;
      unsigned numConformances, numInheritedTypes;
      ArrayRef<uint64_t> rawInheritedAndDependencyIDs;

      decls_block::StructLayout::readRecord(scratch, nameID, contextID,
                                            isImplicit, isObjC, genericSigID,
                                            rawAccessLevel,
                                            numConformances, numInheritedTypes,
                                            rawInheritedAndDependencyIDs);

      Identifier name = MF.getIdentifier(nameID);

      for (TypeID dependencyID :
         rawInheritedAndDependencyIDs.slice(numInheritedTypes)) {
         auto dependency = MF.getTypeChecked(dependencyID);
         if (!dependency) {
            return llvm::make_error<TypeError>(
               name, takeErrorInfo(dependency.takeError()));
         }
      }

      auto DC = MF.getDeclContext(contextID);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto genericParams = MF.maybeReadGenericParams(DC);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto theStruct = MF.createDecl<StructDecl>(SourceLoc(), name, SourceLoc(),
                                                 None, genericParams, DC);
      declOrOffset = theStruct;

      // Read the generic environment.
      theStruct->setGenericSignature(MF.getGenericSignature(genericSigID));

      if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
         theStruct->setAccess(*accessLevel);
      else
         MF.fatal();

      theStruct->setAddedImplicitInitializers();
      if (isImplicit)
         theStruct->setImplicit();
      theStruct->setIsObjC(isObjC);

      handleInherited(theStruct,
                      rawInheritedAndDependencyIDs.slice(0, numInheritedTypes));

      theStruct->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());
      skipRecord(MF.DeclTypeCursor, decls_block::MEMBERS);
      theStruct->setConformanceLoader(
         &MF,
         encodeLazyConformanceContextData(numConformances,
                                          MF.DeclTypeCursor.GetCurrentBitNo()));

      return theStruct;
   }

   Expected<Decl *> deserializeConstructor(ArrayRef<uint64_t> scratch,
                                           StringRef blobData) {
      DeclContextID contextID;
      bool isIUO, isFailable;
      bool isImplicit, isObjC, hasStubImplementation, throws;
      GenericSignatureID genericSigID;
      uint8_t storedInitKind, rawAccessLevel;
      DeclID overriddenID;
      bool needsNewVTableEntry, firstTimeRequired;
      unsigned numArgNames;
      ArrayRef<uint64_t> argNameAndDependencyIDs;

      decls_block::ConstructorLayout::readRecord(scratch, contextID,
                                                 isFailable, isIUO, isImplicit,
                                                 isObjC, hasStubImplementation,
                                                 throws, storedInitKind,
                                                 genericSigID,
                                                 overriddenID,
                                                 rawAccessLevel,
                                                 needsNewVTableEntry,
                                                 firstTimeRequired,
                                                 numArgNames,
                                                 argNameAndDependencyIDs);

      // Resolve the name ids.
      SmallVector<Identifier, 2> argNames;
      for (auto argNameID : argNameAndDependencyIDs.slice(0, numArgNames))
         argNames.push_back(MF.getIdentifier(argNameID));
      DeclName name(ctx, DeclBaseName::createConstructor(), argNames);

      Optional<polar::CtorInitializerKind> initKind =
         getActualCtorInitializerKind(storedInitKind);

      DeclDeserializationError::Flags errorFlags;
      unsigned numVTableEntries = 0;
      if (initKind == CtorInitializerKind::Designated)
         errorFlags |= DeclDeserializationError::DesignatedInitializer;
      if (needsNewVTableEntry) {
         numVTableEntries = 1;
         DeclAttributes attrs;
         attrs.setRawAttributeChain(DAttrs);
      }

      auto overridden = MF.getDeclChecked(overriddenID);
      if (!overridden) {
         llvm::consumeError(overridden.takeError());
         return llvm::make_error<OverrideError>(
            name, errorFlags, numVTableEntries);
      }

      for (auto dependencyID : argNameAndDependencyIDs.slice(numArgNames)) {
         auto dependency = MF.getTypeChecked(dependencyID);
         if (!dependency) {
            return llvm::make_error<TypeError>(
               name, takeErrorInfo(dependency.takeError()),
               errorFlags, numVTableEntries);
         }
      }

      auto parent = MF.getDeclContext(contextID);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto *genericParams = MF.maybeReadGenericParams(parent);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto ctor = MF.createDecl<ConstructorDecl>(name, SourceLoc(), isFailable,
         /*FailabilityLoc=*/SourceLoc(),
         /*Throws=*/throws,
         /*ThrowsLoc=*/SourceLoc(),
         /*BodyParams=*/nullptr,
                                                 genericParams, parent);
      declOrOffset = ctor;

      ctor->setGenericSignature(MF.getGenericSignature(genericSigID));

      if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
         ctor->setAccess(*accessLevel);
      else
         MF.fatal();

      auto *bodyParams = MF.readParameterList();
      assert(bodyParams && "missing parameters for constructor");
      ctor->setParameters(bodyParams);

      if (auto errorConvention = MF.maybeReadForeignErrorConvention())
         ctor->setForeignErrorConvention(*errorConvention);

      if (auto bodyText = MF.maybeReadInlinableBodyText())
         ctor->setBodyStringRepresentation(*bodyText);

      if (isImplicit)
         ctor->setImplicit();
      ctor->setIsObjC(isObjC);
      if (hasStubImplementation)
         ctor->setStubImplementation(true);
      if (initKind.hasValue())
         ctx.evaluator.cacheOutput(InitKindRequest{ctor},
                                   std::move(initKind.getValue()));
      ctx.evaluator.cacheOutput(NeedsNewVTableEntryRequest{ctor},
                                std::move(needsNewVTableEntry));

      ctor->setOverriddenDecl(cast_or_null<ConstructorDecl>(overridden.get()));
      if (auto *overridden = ctor->getOverriddenDecl()) {
         if (!attributeChainContains<RequiredAttr>(DAttrs) ||
             !overridden->isRequired()) {
            // FIXME: why is a convenience init considered overridden when the
            // overriding init can't be marked overriding in source?
            if (!overridden->isConvenienceInit())
               AddAttribute(new (ctx) OverrideAttr(SourceLoc()));
         }
      }

      ctor->setImplicitlyUnwrappedOptional(isIUO);

      return ctor;
   }

   Expected<Decl *> deserializeVar(ArrayRef<uint64_t> scratch,
                                   StringRef blobData) {
      IdentifierID nameID;
      DeclContextID contextID;
      bool isImplicit, isObjC, isStatic, hasNonPatternBindingInit;
      uint8_t rawIntroducer;
      bool isGetterMutating, isSetterMutating;
      bool isLazyStorageProperty;
      DeclID lazyStorageID;
      unsigned numAccessors, numBackingProperties;
      uint8_t readImpl, writeImpl, readWriteImpl, opaqueReadOwnership;
      uint8_t rawAccessLevel, rawSetterAccessLevel;
      TypeID interfaceTypeID;
      bool isIUO;
      ModuleFile::AccessorRecord accessors;
      DeclID overriddenID, opaqueReturnTypeID;
      unsigned numVTableEntries;
      ArrayRef<uint64_t> arrayFieldIDs;

      decls_block::VarLayout::readRecord(scratch, nameID, contextID,
                                         isImplicit, isObjC, isStatic, rawIntroducer,
                                         hasNonPatternBindingInit,
                                         isGetterMutating, isSetterMutating,
                                         isLazyStorageProperty,
                                         lazyStorageID,
                                         opaqueReadOwnership,
                                         readImpl, writeImpl, readWriteImpl,
                                         numAccessors,
                                         interfaceTypeID,
                                         isIUO,
                                         overriddenID,
                                         rawAccessLevel, rawSetterAccessLevel,
                                         opaqueReturnTypeID,
                                         numBackingProperties,
                                         numVTableEntries,
                                         arrayFieldIDs);

      Identifier name = MF.getIdentifier(nameID);

      auto getErrorFlags = [&]() {
         // Stored properties in classes still impact class object layout because
         // their offset is computed and stored in the field offset vector.
         DeclDeserializationError::Flags errorFlags;

         if (!isStatic) {
            auto actualReadImpl = getActualReadImplKind(readImpl);
            if (actualReadImpl && *actualReadImpl == ReadImplKind::Stored) {
               errorFlags |= DeclDeserializationError::Flag::NeedsFieldOffsetVectorEntry;
            }
         }

         return errorFlags;
      };

      Expected<Decl *> overridden = MF.getDeclChecked(overriddenID);
      if (!overridden) {
         llvm::consumeError(overridden.takeError());

         return llvm::make_error<OverrideError>(
            name, getErrorFlags(), numVTableEntries);
      }

      // Extract the accessor IDs.
      for (DeclID accessorID : arrayFieldIDs.slice(0, numAccessors)) {
         accessors.IDs.push_back(accessorID);
      }
      arrayFieldIDs = arrayFieldIDs.slice(numAccessors);

      // Extract the backing property IDs.
      auto backingPropertyIDs = arrayFieldIDs.slice(0, numBackingProperties);
      arrayFieldIDs = arrayFieldIDs.slice(numBackingProperties);

      for (TypeID dependencyID : arrayFieldIDs) {
         auto dependency = MF.getTypeChecked(dependencyID);
         if (!dependency) {
            return llvm::make_error<TypeError>(
               name, takeErrorInfo(dependency.takeError()),
               getErrorFlags(), numVTableEntries);
         }
      }

      auto DC = MF.getDeclContext(contextID);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto introducer = getActualVarDeclIntroducer(
         (serialization::VarDeclIntroducer) rawIntroducer);
      if (!introducer)
         MF.fatal();

      auto var = MF.createDecl<VarDecl>(/*IsStatic*/ isStatic, *introducer,
         /*IsCaptureList*/ false, SourceLoc(),
                                                     name, DC);
      var->setHasNonPatternBindingInit(hasNonPatternBindingInit);
      var->setIsGetterMutating(isGetterMutating);
      var->setIsSetterMutating(isSetterMutating);
      declOrOffset = var;

      Type interfaceType = MF.getType(interfaceTypeID);
      var->setInterfaceType(interfaceType);
      var->setImplicitlyUnwrappedOptional(isIUO);

      if (auto referenceStorage = interfaceType->getAs<ReferenceStorageType>())
         AddAttribute(
            new (ctx) ReferenceOwnershipAttr(referenceStorage->getOwnership()));

      MF.configureStorage(var, opaqueReadOwnership,
                          readImpl, writeImpl, readWriteImpl, accessors);
      auto accessLevel = getActualAccessLevel(rawAccessLevel);
      if (!accessLevel)
         MF.fatal();

      var->setAccess(*accessLevel);

      if (var->isSettable(nullptr)) {
         auto setterAccess = getActualAccessLevel(rawSetterAccessLevel);
         if (!setterAccess)
            MF.fatal();
         var->setSetterAccess(*setterAccess);

         // If we have a less-accessible setter, honor that by adding the
         // setter access attribute.
         if (*setterAccess < *accessLevel) {
            AddAttribute(
               new (ctx) SetterAccessAttr(SourceLoc(), SourceLoc(),
                                          *setterAccess, /*implicit*/true));
         }
      }

      if (isImplicit)
         var->setImplicit();
      var->setIsObjC(isObjC);

      var->setOverriddenDecl(cast_or_null<VarDecl>(overridden.get()));
      if (var->getOverriddenDecl())
         AddAttribute(new (ctx) OverrideAttr(SourceLoc()));

      // Add the @_hasStorage attribute if this var has storage.
      if (var->hasStorage())
         AddAttribute(new (ctx) HasStorageAttr(/*isImplicit:*/true));

      if (opaqueReturnTypeID) {
         ctx.evaluator.cacheOutput(
            OpaqueResultTypeRequest{var},
            cast<OpaqueTypeDecl>(MF.getDecl(opaqueReturnTypeID)));
      }

      // If this is a lazy property, record its backing storage.
      if (lazyStorageID) {
         VarDecl *storage = cast<VarDecl>(MF.getDecl(lazyStorageID));
         ctx.evaluator.cacheOutput(
            LazyStoragePropertyRequest{var}, std::move(storage));
      }

      var->setLazyStorageProperty(isLazyStorageProperty);

      // If there are any backing properties, record them.
      if (numBackingProperties > 0) {
         auto backingDecl = MF.getDeclChecked(backingPropertyIDs[0]);
         if (!backingDecl) {
            if (numBackingProperties > 1 &&
                backingDecl.errorIsA<XRefNonLoadedModuleError>()) {
               // A property wrapper defined behind an implementation-only import
               // is safe to drop when it can't be deserialized.
               // rdar://problem/56599179
               consumeError(backingDecl.takeError());
            } else
               return backingDecl.takeError();
         }

         VarDecl *backingVar = cast<VarDecl>(backingDecl.get());
         VarDecl *storageWrapperVar = nullptr;
         if (numBackingProperties > 1) {
            storageWrapperVar = cast<VarDecl>(MF.getDecl(backingPropertyIDs[1]));
         }

         PropertyWrapperBackingPropertyInfo info(
            backingVar, storageWrapperVar, nullptr, nullptr, nullptr);
         ctx.evaluator.cacheOutput(
            PropertyWrapperBackingPropertyInfoRequest{var}, std::move(info));
         ctx.evaluator.cacheOutput(
            PropertyWrapperBackingPropertyTypeRequest{var},
            backingVar->getInterfaceType());
         backingVar->setOriginalWrappedProperty(var);

         if (storageWrapperVar)
            storageWrapperVar->setOriginalWrappedProperty(var);
      }

      return var;
   }

   Expected<Decl *> deserializeParam(ArrayRef<uint64_t> scratch,
                                     StringRef blobData) {
      IdentifierID argNameID, paramNameID;
      DeclContextID contextID;
      unsigned rawSpecifier;
      TypeID interfaceTypeID;
      bool isIUO;
      bool isVariadic;
      bool isAutoClosure;
      uint8_t rawDefaultArg;

      decls_block::ParamLayout::readRecord(scratch, argNameID, paramNameID,
                                           contextID, rawSpecifier,
                                           interfaceTypeID, isIUO, isVariadic,
                                           isAutoClosure, rawDefaultArg);

      auto DC = MF.getDeclContext(contextID);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto specifier = getActualParamDeclSpecifier(
         (serialization::ParamDeclSpecifier)rawSpecifier);
      if (!specifier)
         MF.fatal();

      auto param = MF.createDecl<ParamDecl>(SourceLoc(), SourceLoc(),
                                            MF.getIdentifier(argNameID),
                                            SourceLoc(),
                                            MF.getIdentifier(paramNameID), DC);
      param->setSpecifier(*specifier);

      declOrOffset = param;

      auto paramTy = MF.getType(interfaceTypeID);
      if (paramTy->hasError()) {
         // FIXME: This should never happen, because we don't serialize
         // error types.
         DC->printContext(llvm::errs());
         paramTy->dump(llvm::errs());
         MF.fatal();
      }

      param->setInterfaceType(paramTy);
      param->setImplicitlyUnwrappedOptional(isIUO);
      param->setVariadic(isVariadic);
      param->setAutoClosure(isAutoClosure);

      // Decode the default argument kind.
      // FIXME: Default argument expression, if available.
      if (auto defaultArg = getActualDefaultArgKind(rawDefaultArg)) {
         param->setDefaultArgumentKind(*defaultArg);
         if (!blobData.empty())
            param->setDefaultValueStringRepresentation(blobData);
      }
      return param;
   }

   Expected<Decl *> deserializeAnyFunc(ArrayRef<uint64_t> scratch,
                                       StringRef blobData,
                                       bool isAccessor) {
      DeclContextID contextID;
      bool isImplicit;
      bool isStatic;
      uint8_t rawStaticSpelling, rawAccessLevel, rawMutModifier;
      uint8_t rawAccessorKind;
      bool isObjC, hasForcedStaticDispatch, throws;
      unsigned numNameComponentsBiased;
      GenericSignatureID genericSigID;
      TypeID resultInterfaceTypeID;
      bool isIUO;
      DeclID associatedDeclID;
      DeclID overriddenID;
      DeclID accessorStorageDeclID;
      bool overriddenAffectsABI, needsNewVTableEntry, isTransparent;
      DeclID opaqueReturnTypeID;
      ArrayRef<uint64_t> nameAndDependencyIDs;

      if (!isAccessor) {
         decls_block::FuncLayout::readRecord(scratch, contextID, isImplicit,
                                             isStatic, rawStaticSpelling, isObjC,
                                             rawMutModifier,
                                             hasForcedStaticDispatch, throws,
                                             genericSigID,
                                             resultInterfaceTypeID,
                                             isIUO,
                                             associatedDeclID, overriddenID,
                                             overriddenAffectsABI,
                                             numNameComponentsBiased,
                                             rawAccessLevel,
                                             needsNewVTableEntry,
                                             opaqueReturnTypeID,
                                             nameAndDependencyIDs);
      } else {
         decls_block::AccessorLayout::readRecord(scratch, contextID, isImplicit,
                                                 isStatic, rawStaticSpelling, isObjC,
                                                 rawMutModifier,
                                                 hasForcedStaticDispatch, throws,
                                                 genericSigID,
                                                 resultInterfaceTypeID,
                                                 isIUO,
                                                 overriddenID,
                                                 overriddenAffectsABI,
                                                 accessorStorageDeclID,
                                                 rawAccessorKind,
                                                 rawAccessLevel,
                                                 needsNewVTableEntry,
                                                 isTransparent,
                                                 nameAndDependencyIDs);
      }

      DeclDeserializationError::Flags errorFlags;
      unsigned numVTableEntries = needsNewVTableEntry ? 1 : 0;

      // Parse the accessor-specific fields.
      AbstractStorageDecl *storage = nullptr;
      AccessorKind accessorKind;
      if (isAccessor) {
         auto storageResult = MF.getDeclChecked(accessorStorageDeclID);
         if (!storageResult ||
             !(storage =
                  dyn_cast_or_null<AbstractStorageDecl>(storageResult.get()))) {
            // FIXME: "TypeError" isn't exactly correct for this.
            return llvm::make_error<TypeError>(
               DeclName(), takeErrorInfo(storageResult.takeError()),
               errorFlags, numVTableEntries);
         }

         if (auto accessorKindResult = getActualAccessorKind(rawAccessorKind))
            accessorKind = *accessorKindResult;
         else
            MF.fatal();

         // Deserializing the storage declaration will cause a recurrence
         // into this code.  When we come out, don't create the accessor twice.
         // TODO: find some better way of breaking this cycle, like lazily
         // deserializing the accessors.
         if (auto accessor = storage->getAccessor(accessorKind))
            return accessor;
      }

      // Resolve the name ids.
      DeclName name;
      ArrayRef<uint64_t> dependencyIDs;
      if (isAccessor) {
         dependencyIDs = nameAndDependencyIDs;
      } else {
         Identifier baseName = MF.getIdentifier(nameAndDependencyIDs.front());
         if (numNameComponentsBiased != 0) {
            SmallVector<Identifier, 2> names;
            for (auto nameID : nameAndDependencyIDs.slice(1,
                                                          numNameComponentsBiased-1)){
               names.push_back(MF.getIdentifier(nameID));
            }
            name = DeclName(ctx, baseName, names);
            dependencyIDs = nameAndDependencyIDs.slice(numNameComponentsBiased);
         } else {
            name = baseName;
            dependencyIDs = nameAndDependencyIDs.drop_front();
         }
      }

      Expected<Decl *> overriddenOrError = MF.getDeclChecked(overriddenID);
      Decl *overridden;
      if (overriddenOrError) {
         overridden = overriddenOrError.get();
      } else {
         llvm::consumeError(overriddenOrError.takeError());

         if (overriddenAffectsABI || !ctx.LangOpts.EnableDeserializationRecovery) {
            return llvm::make_error<OverrideError>(
               name, errorFlags, numVTableEntries);
         }

         overridden = nullptr;
      }

      for (TypeID dependencyID : dependencyIDs) {
         auto dependency = MF.getTypeChecked(dependencyID);
         if (!dependency) {
            return llvm::make_error<TypeError>(
               name, takeErrorInfo(dependency.takeError()),
               errorFlags, numVTableEntries);
         }
      }

      auto DC = MF.getDeclContext(contextID);
      if (declOrOffset.isComplete())
         return declOrOffset;

      // Read generic params before reading the type, because the type may
      // reference generic parameters, and we want them to have a dummy
      // DeclContext for now.
      GenericParamList *genericParams = MF.maybeReadGenericParams(DC);

      auto staticSpelling = getActualStaticSpellingKind(rawStaticSpelling);
      if (!staticSpelling.hasValue())
         MF.fatal();

      if (declOrOffset.isComplete())
         return declOrOffset;

      FuncDecl *fn;
      if (!isAccessor) {
         fn = FuncDecl::createDeserialized(
            ctx, /*StaticLoc=*/SourceLoc(), staticSpelling.getValue(),
            /*FuncLoc=*/SourceLoc(), name, /*NameLoc=*/SourceLoc(),
            /*Throws=*/throws, /*ThrowsLoc=*/SourceLoc(),
            genericParams, DC);
      } else {
         auto *accessor = AccessorDecl::createDeserialized(
            ctx, /*FuncLoc=*/SourceLoc(), /*AccessorKeywordLoc=*/SourceLoc(),
            accessorKind, storage,
            /*StaticLoc=*/SourceLoc(), staticSpelling.getValue(),
            /*Throws=*/throws, /*ThrowsLoc=*/SourceLoc(),
            genericParams, DC);
         accessor->setIsTransparent(isTransparent);

         fn = accessor;
      }
      declOrOffset = fn;

      fn->setGenericSignature(MF.getGenericSignature(genericSigID));

      if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
         fn->setAccess(*accessLevel);
      else
         MF.fatal();

      if (auto SelfAccessKind = getActualSelfAccessKind(rawMutModifier))
         fn->setSelfAccessKind(*SelfAccessKind);
      else
         MF.fatal();

      if (!isAccessor) {
         if (Decl *associated = MF.getDecl(associatedDeclID)) {
            if (auto op = dyn_cast<OperatorDecl>(associated)) {
               ctx.evaluator.cacheOutput(FunctionOperatorRequest{fn},
                                         std::move(op));

               if (isa<PrefixOperatorDecl>(op))
                  fn->getAttrs().add(new (ctx) PrefixAttr(/*implicit*/false));
               else if (isa<PostfixOperatorDecl>(op))
                  fn->getAttrs().add(new (ctx) PostfixAttr(/*implicit*/false));
               // Note that an explicit 'infix' is not required.
            }
            // Otherwise, unknown associated decl kind.
         }
      }

      fn->setStatic(isStatic);

      fn->getBodyResultTypeLoc().setType(MF.getType(resultInterfaceTypeID));
      fn->setImplicitlyUnwrappedOptional(isIUO);

      ParameterList *paramList = MF.readParameterList();
      fn->setParameters(paramList);

      if (auto errorConvention = MF.maybeReadForeignErrorConvention())
         fn->setForeignErrorConvention(*errorConvention);

      if (auto bodyText = MF.maybeReadInlinableBodyText())
         fn->setBodyStringRepresentation(*bodyText);

      fn->setOverriddenDecl(cast_or_null<FuncDecl>(overridden));
      if (fn->getOverriddenDecl())
         AddAttribute(new (ctx) OverrideAttr(SourceLoc()));

      if (isImplicit)
         fn->setImplicit();
      fn->setIsObjC(isObjC);
      fn->setForcedStaticDispatch(hasForcedStaticDispatch);
      ctx.evaluator.cacheOutput(NeedsNewVTableEntryRequest{fn},
                                std::move(needsNewVTableEntry));

      if (opaqueReturnTypeID) {
         ctx.evaluator.cacheOutput(
            OpaqueResultTypeRequest{fn},
            cast<OpaqueTypeDecl>(MF.getDecl(opaqueReturnTypeID)));
      }

      return fn;
   }

   Expected<Decl *> deserializeFunc(ArrayRef<uint64_t> scratch,
                                    StringRef blobData) {
      return deserializeAnyFunc(scratch, blobData, /*isAccessor*/false);
   }
   Expected<Decl *> deserializeAccessor(ArrayRef<uint64_t> scratch,
                                        StringRef blobData) {
      return deserializeAnyFunc(scratch, blobData, /*isAccessor*/true);
   }

   Expected<Decl *> deserializeOpaqueType(ArrayRef<uint64_t> scratch,
                                          StringRef blobData) {
      DeclID namingDeclID;
      DeclContextID contextID;
      GenericSignatureID interfaceSigID;
      TypeID interfaceTypeID;
      GenericSignatureID genericSigID;
      SubstitutionMapID underlyingTypeID;

      decls_block::OpaqueTypeLayout::readRecord(scratch, contextID,
                                                namingDeclID, interfaceSigID,
                                                interfaceTypeID, genericSigID,
                                                underlyingTypeID);

      auto declContext = MF.getDeclContext(contextID);
      auto interfaceSig = MF.getGenericSignature(interfaceSigID);
      auto interfaceType = MF.getType(interfaceTypeID)
         ->castTo<GenericTypeParamType>();

      // Check for reentrancy.
      if (declOrOffset.isComplete())
         return cast<OpaqueTypeDecl>(declOrOffset.get());

      // Create the decl.
      auto opaqueDecl =
         new (ctx) OpaqueTypeDecl(nullptr, nullptr, declContext,
                                  interfaceSig, interfaceType);
      declOrOffset = opaqueDecl;

      auto namingDecl = cast<ValueDecl>(MF.getDecl(namingDeclID));
      opaqueDecl->setNamingDecl(namingDecl);

      if (auto genericParams = MF.maybeReadGenericParams(opaqueDecl)) {
         ctx.evaluator.cacheOutput(GenericParamListRequest{opaqueDecl},
                                   std::move(genericParams));
      }

      auto genericSig = MF.getGenericSignature(genericSigID);
      if (genericSig)
         opaqueDecl->setGenericSignature(genericSig);
      if (underlyingTypeID)
         opaqueDecl->setUnderlyingTypeSubstitutions(
            MF.getSubstitutionMap(underlyingTypeID));
      SubstitutionMap subs;
      if (genericSig) {
         subs = genericSig->getIdentitySubstitutionMap();
      }
      auto opaqueTy = OpaqueTypeArchetypeType::get(opaqueDecl, subs);
      auto metatype = MetatypeType::get(opaqueTy);
      opaqueDecl->setInterfaceType(metatype);
      return opaqueDecl;
   }

   Expected<Decl *> deserializePatternBinding(ArrayRef<uint64_t> scratch,
                                              StringRef blobData) {
      DeclContextID contextID;
      bool isImplicit;
      bool isStatic;
      uint8_t RawStaticSpelling;
      unsigned numPatterns;
      ArrayRef<uint64_t> initContextIDs;

      decls_block::PatternBindingLayout::readRecord(scratch, contextID,
                                                    isImplicit,
                                                    isStatic,
                                                    RawStaticSpelling,
                                                    numPatterns,
                                                    initContextIDs);
      auto StaticSpelling = getActualStaticSpellingKind(RawStaticSpelling);
      if (!StaticSpelling.hasValue())
         MF.fatal();

      auto dc = MF.getDeclContext(contextID);

      SmallVector<std::pair<Pattern *, DeclContextID>, 4> patterns;
      for (unsigned i = 0; i != numPatterns; ++i) {
         auto pattern = MF.readPattern(dc);
         if (!pattern) {
            // Silently drop the pattern...
            llvm::consumeError(pattern.takeError());
            // ...but continue to read any further patterns we're expecting.
            continue;
         }

         patterns.emplace_back(pattern.get(), DeclContextID());
         if (!initContextIDs.empty()) {
            patterns.back().second =
               DeclContextID::getFromOpaqueValue(initContextIDs[i]);
         }
      }

      auto binding =
         PatternBindingDecl::createDeserialized(ctx, SourceLoc(),
                                                StaticSpelling.getValue(),
                                                SourceLoc(), patterns.size(), dc);
      declOrOffset = binding;

      binding->setStatic(isStatic);

      if (isImplicit)
         binding->setImplicit();

      for (unsigned i = 0; i != patterns.size(); ++i) {
         DeclContext *initContext = MF.getDeclContext(patterns[i].second);
         binding->setPattern(i, patterns[i].first, initContext);
      }

      return binding;
   }

   Expected<Decl *> deserializeInterface(ArrayRef<uint64_t> scratch,
                                        StringRef blobData) {
      IdentifierID nameID;
      DeclContextID contextID;
      bool isImplicit, isClassBounded, isObjC, existentialTypeSupported;
      uint8_t rawAccessLevel;
      unsigned numInheritedTypes;
      ArrayRef<uint64_t> rawInheritedAndDependencyIDs;

      decls_block::InterfaceLayout::readRecord(scratch, nameID, contextID,
                                              isImplicit, isClassBounded, isObjC,
                                              existentialTypeSupported,
                                              rawAccessLevel, numInheritedTypes,
                                              rawInheritedAndDependencyIDs);

      Identifier name = MF.getIdentifier(nameID);

      for (TypeID dependencyID :
         rawInheritedAndDependencyIDs.slice(numInheritedTypes)) {
         auto dependency = MF.getTypeChecked(dependencyID);
         if (!dependency) {
            return llvm::make_error<TypeError>(
               name, takeErrorInfo(dependency.takeError()));
         }
      }

      auto DC = MF.getDeclContext(contextID);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto proto = MF.createDecl<InterfaceDecl>(DC, SourceLoc(), SourceLoc(), name,
                                               None, /*TrailingWhere=*/nullptr);
      declOrOffset = proto;

      ctx.evaluator.cacheOutput(InterfaceRequiresClassRequest{proto},
                                std::move(isClassBounded));
      ctx.evaluator.cacheOutput(ExistentialTypeSupportedRequest{proto},
                                std::move(existentialTypeSupported));

      if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
         proto->setAccess(*accessLevel);
      else
         MF.fatal();

      auto genericParams = MF.maybeReadGenericParams(DC);
      assert(genericParams && "protocol with no generic parameters?");
      ctx.evaluator.cacheOutput(GenericParamListRequest{proto},
                                std::move(genericParams));

      handleInherited(proto,
                      rawInheritedAndDependencyIDs.slice(0, numInheritedTypes));

      if (isImplicit)
         proto->setImplicit();
      proto->setIsObjC(isObjC);

      proto->setLazyRequirementSignature(&MF,
                                         MF.DeclTypeCursor.GetCurrentBitNo());
      if (llvm::Error Err = skipGenericRequirements(MF.DeclTypeCursor))
         MF.fatal(std::move(Err));

      proto->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());

      return proto;
   }

   template <typename OperatorLayout, typename OperatorDecl>
   Expected<Decl *> deserializeUnaryOperator(ArrayRef<uint64_t> scratch,
                                             StringRef blobData) {
      IdentifierID nameID;
      DeclContextID contextID;
      ArrayRef<uint64_t> designatedNominalTypeDeclIDs;

      OperatorLayout::readRecord(scratch, nameID, contextID,
                                 designatedNominalTypeDeclIDs);
      auto DC = MF.getDeclContext(contextID);

      SmallVector<NominalTypeDecl *, 1> designatedNominalTypes;
      for (auto id : designatedNominalTypeDeclIDs) {
         Expected<Decl *> nominal = MF.getDeclChecked(id);
         if (!nominal)
            return nominal.takeError();
         designatedNominalTypes.push_back(cast<NominalTypeDecl>(nominal.get()));
      }

      auto result = MF.createDecl<OperatorDecl>(
         DC, SourceLoc(), MF.getIdentifier(nameID), SourceLoc(),
         ctx.AllocateCopy(designatedNominalTypes));

      declOrOffset = result;
      return result;
   }

   Expected<Decl *> deserializePrefixOperator(ArrayRef<uint64_t> scratch,
                                              StringRef blobData) {
      return deserializeUnaryOperator<decls_block::PrefixOperatorLayout,
         PrefixOperatorDecl>(scratch, blobData);
   }

   Expected<Decl *> deserializePostfixOperator(ArrayRef<uint64_t> scratch,
                                               StringRef blobData) {
      return deserializeUnaryOperator<decls_block::PostfixOperatorLayout,
         PostfixOperatorDecl>(scratch, blobData);
   }

   Expected<Decl *> deserializeInfixOperator(ArrayRef<uint64_t> scratch,
                                             StringRef blobData) {
      IdentifierID nameID;
      DeclContextID contextID;
      DeclID precedenceGroupID;
      ArrayRef<uint64_t> designatedNominalTypeDeclIDs;

      decls_block::InfixOperatorLayout::readRecord(scratch, nameID, contextID,
                                                   precedenceGroupID,
                                                   designatedNominalTypeDeclIDs);

      Expected<Decl *> precedenceGroup = MF.getDeclChecked(precedenceGroupID);
      if (!precedenceGroup)
         return precedenceGroup.takeError();

      auto DC = MF.getDeclContext(contextID);

      SmallVector<NominalTypeDecl *, 1> designatedNominalTypes;
      for (auto id : designatedNominalTypeDeclIDs) {
         Expected<Decl *> nominal = MF.getDeclChecked(id);
         if (!nominal)
            return nominal.takeError();
         designatedNominalTypes.push_back(cast<NominalTypeDecl>(nominal.get()));
      }

      auto result = MF.createDecl<InfixOperatorDecl>(
         DC, SourceLoc(), MF.getIdentifier(nameID), SourceLoc(), SourceLoc(),
         ArrayRef<Identifier>{}, ArrayRef<SourceLoc>{});
      result->setDesignatedNominalTypes(ctx.AllocateCopy(designatedNominalTypes));
      ctx.evaluator.cacheOutput(
         OperatorPrecedenceGroupRequest{result},
         std::move(cast_or_null<PrecedenceGroupDecl>(precedenceGroup.get())));

      declOrOffset = result;
      return result;
   }

   Expected<Decl *> deserializePrecedenceGroup(ArrayRef<uint64_t> scratch,
                                               StringRef blobData) {
      IdentifierID nameID;
      DeclContextID contextID;
      uint8_t rawAssociativity;
      bool assignment;
      unsigned numHigherThan;
      ArrayRef<uint64_t> rawRelations;

      decls_block::PrecedenceGroupLayout::readRecord(scratch, nameID, contextID,
                                                     rawAssociativity,
                                                     assignment, numHigherThan,
                                                     rawRelations);

      auto DC = MF.getDeclContext(contextID);

      auto associativity = getActualAssociativity(rawAssociativity);
      if (!associativity.hasValue())
         MF.fatal();

      if (numHigherThan > rawRelations.size())
         MF.fatal();

      SmallVector<PrecedenceGroupDecl::Relation, 4> higherThan;
      for (auto relID : rawRelations.slice(0, numHigherThan)) {
         PrecedenceGroupDecl *rel = nullptr;
         if (relID)
            rel = dyn_cast_or_null<PrecedenceGroupDecl>(MF.getDecl(relID));
         if (!rel)
            MF.fatal();

         higherThan.push_back({SourceLoc(), rel->getName(), rel});
      }

      SmallVector<PrecedenceGroupDecl::Relation, 4> lowerThan;
      for (auto relID : rawRelations.slice(numHigherThan)) {
         PrecedenceGroupDecl *rel = nullptr;
         if (relID)
            rel = dyn_cast_or_null<PrecedenceGroupDecl>(MF.getDecl(relID));
         if (!rel)
            MF.fatal();

         lowerThan.push_back({SourceLoc(), rel->getName(), rel});
      }

      declOrOffset = PrecedenceGroupDecl::create(DC, SourceLoc(), SourceLoc(),
                                                 MF.getIdentifier(nameID),
                                                 SourceLoc(),
                                                 SourceLoc(), SourceLoc(),
                                                 *associativity,
                                                 SourceLoc(), SourceLoc(),
                                                 assignment,
                                                 SourceLoc(), higherThan,
                                                 SourceLoc(), lowerThan,
                                                 SourceLoc());
      return declOrOffset.get();
   }

   Expected<Decl *> deserializeClass(ArrayRef<uint64_t> scratch,
                                     StringRef blobData) {
      IdentifierID nameID;
      DeclContextID contextID;
      bool isImplicit, isObjC;
      bool inheritsSuperclassInitializers;
      GenericSignatureID genericSigID;
      TypeID superclassID;
      uint8_t rawAccessLevel;
      unsigned numConformances, numInheritedTypes;
      ArrayRef<uint64_t> rawInheritedAndDependencyIDs;
      decls_block::ClassLayout::readRecord(scratch, nameID, contextID,
                                           isImplicit, isObjC,
                                           inheritsSuperclassInitializers,
                                           genericSigID, superclassID,
                                           rawAccessLevel, numConformances,
                                           numInheritedTypes,
                                           rawInheritedAndDependencyIDs);

      Identifier name = MF.getIdentifier(nameID);

      for (TypeID dependencyID :
         rawInheritedAndDependencyIDs.slice(numInheritedTypes)) {
         auto dependency = MF.getTypeChecked(dependencyID);
         if (!dependency) {
            return llvm::make_error<TypeError>(
               name, takeErrorInfo(dependency.takeError()));
         }
      }

      auto DC = MF.getDeclContext(contextID);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto genericParams = MF.maybeReadGenericParams(DC);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto theClass = MF.createDecl<ClassDecl>(SourceLoc(), name, SourceLoc(),
                                               None, genericParams, DC);
      declOrOffset = theClass;

      theClass->setGenericSignature(MF.getGenericSignature(genericSigID));

      if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
         theClass->setAccess(*accessLevel);
      else
         MF.fatal();

      theClass->setAddedImplicitInitializers();
      if (isImplicit)
         theClass->setImplicit();
      theClass->setIsObjC(isObjC);
      theClass->setSuperclass(MF.getType(superclassID));
      ctx.evaluator.cacheOutput(InheritsSuperclassInitializersRequest{theClass},
                                std::move(inheritsSuperclassInitializers));

      handleInherited(theClass,
                      rawInheritedAndDependencyIDs.slice(0, numInheritedTypes));

      theClass->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());
      skipRecord(MF.DeclTypeCursor, decls_block::MEMBERS);
      theClass->setConformanceLoader(
         &MF,
         encodeLazyConformanceContextData(numConformances,
                                          MF.DeclTypeCursor.GetCurrentBitNo()));
      return theClass;
   }

   Expected<Decl *> deserializeEnum(ArrayRef<uint64_t> scratch,
                                    StringRef blobData) {
      IdentifierID nameID;
      DeclContextID contextID;
      bool isImplicit;
      bool isObjC;
      GenericSignatureID genericSigID;
      TypeID rawTypeID;
      uint8_t rawAccessLevel;
      unsigned numConformances, numInherited;
      ArrayRef<uint64_t> rawInheritedAndDependencyIDs;

      decls_block::EnumLayout::readRecord(scratch, nameID, contextID,
                                          isImplicit, isObjC, genericSigID,
                                          rawTypeID, rawAccessLevel,
                                          numConformances, numInherited,
                                          rawInheritedAndDependencyIDs);

      auto DC = MF.getDeclContext(contextID);
      if (declOrOffset.isComplete())
         return declOrOffset;

      Identifier name = MF.getIdentifier(nameID);
      for (TypeID dependencyID :
         rawInheritedAndDependencyIDs.slice(numInherited)) {
         auto dependency = MF.getTypeChecked(dependencyID);
         if (!dependency) {
            return llvm::make_error<TypeError>(
               name, takeErrorInfo(dependency.takeError()));
         }
      }

      auto genericParams = MF.maybeReadGenericParams(DC);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto theEnum = MF.createDecl<EnumDecl>(SourceLoc(), name, SourceLoc(), None,
                                             genericParams, DC);

      declOrOffset = theEnum;

      theEnum->setGenericSignature(MF.getGenericSignature(genericSigID));

      if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
         theEnum->setAccess(*accessLevel);
      else
         MF.fatal();

      theEnum->setAddedImplicitInitializers();
      // @objc enums have all their raw values checked.
      if (isObjC) {
         theEnum->setHasFixedRawValues();
      }

      if (isImplicit)
         theEnum->setImplicit();
      theEnum->setIsObjC(isObjC);

      theEnum->setRawType(MF.getType(rawTypeID));

      auto rawInheritedIDs = rawInheritedAndDependencyIDs.slice(0, numInherited);
      handleInherited(theEnum, rawInheritedIDs);

      theEnum->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());
      skipRecord(MF.DeclTypeCursor, decls_block::MEMBERS);
      theEnum->setConformanceLoader(
         &MF,
         encodeLazyConformanceContextData(numConformances,
                                          MF.DeclTypeCursor.GetCurrentBitNo()));
      return theEnum;
   }

   Expected<Decl *> deserializeEnumElement(ArrayRef<uint64_t> scratch,
                                           StringRef blobData) {
      DeclContextID contextID;
      bool isImplicit, hasPayload, isRawValueImplicit, isNegative;
      unsigned rawValueKindID;
      IdentifierID rawValueData;
      unsigned numArgNames;
      ArrayRef<uint64_t> argNameAndDependencyIDs;

      decls_block::EnumElementLayout::readRecord(scratch, contextID,
                                                 isImplicit, hasPayload,
                                                 rawValueKindID,
                                                 isRawValueImplicit, isNegative,
                                                 rawValueData,
                                                 numArgNames,
                                                 argNameAndDependencyIDs);

      // Resolve the name ids.
      Identifier baseName = MF.getIdentifier(argNameAndDependencyIDs.front());
      SmallVector<Identifier, 2> argNames;
      for (auto argNameID : argNameAndDependencyIDs.slice(1, numArgNames-1))
         argNames.push_back(MF.getIdentifier(argNameID));
      DeclName compoundName(ctx, baseName, argNames);
      DeclName name = argNames.empty() ? baseName : compoundName;

      for (TypeID dependencyID : argNameAndDependencyIDs.slice(numArgNames)) {
         auto dependency = MF.getTypeChecked(dependencyID);
         if (!dependency) {
            // Enum elements never introduce missing members in their parent enum.
            //
            // A frozen enum cannot be laid out if its missing cases anyway,
            // so the dependency mechanism ensures the entire enum fails to
            // deserialize.
            //
            // For a resilient enum, we don't care and just drop the element
            // and continue.
            return llvm::make_error<TypeError>(
               name, takeErrorInfo(dependency.takeError()));
         }
      }

      DeclContext *DC = MF.getDeclContext(contextID);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto elem = MF.createDecl<EnumElementDecl>(SourceLoc(),
                                                 name,
                                                 nullptr,
                                                 SourceLoc(),
                                                 nullptr,
                                                 DC);
      declOrOffset = elem;

      // Read payload parameter list, if it exists.
      if (hasPayload) {
         auto *paramList = MF.readParameterList();
         elem->setParameterList(paramList);
      }

      // Deserialize the literal raw value, if any.
      switch ((EnumElementRawValueKind)rawValueKindID) {
         case EnumElementRawValueKind::None:
            break;
         case EnumElementRawValueKind::IntegerLiteral: {
            auto literalText = MF.getIdentifierText(rawValueData);
            auto literal = new (ctx) IntegerLiteralExpr(literalText, SourceLoc(),
                                                        isRawValueImplicit);
            if (isNegative)
               literal->setNegative(SourceLoc());
            elem->setRawValueExpr(literal);
         }
      }

      if (isImplicit)
         elem->setImplicit();
      elem->setAccess(std::max(cast<EnumDecl>(DC)->getFormalAccess(),
                               AccessLevel::Internal));

      return elem;
   }

   Expected<Decl *> deserializeSubscript(ArrayRef<uint64_t> scratch,
                                         StringRef blobData) {
      DeclContextID contextID;
      bool isImplicit, isObjC, isGetterMutating, isSetterMutating;
      GenericSignatureID genericSigID;
      TypeID elemInterfaceTypeID;
      bool isIUO;
      ModuleFile::AccessorRecord accessors;
      DeclID overriddenID, opaqueReturnTypeID;
      uint8_t rawAccessLevel, rawSetterAccessLevel, rawStaticSpelling;
      uint8_t opaqueReadOwnership, readImpl, writeImpl, readWriteImpl;
      unsigned numArgNames, numAccessors;
      unsigned numVTableEntries;
      ArrayRef<uint64_t> argNameAndDependencyIDs;

      decls_block::SubscriptLayout::readRecord(scratch, contextID,
                                               isImplicit, isObjC,
                                               isGetterMutating, isSetterMutating,
                                               opaqueReadOwnership,
                                               readImpl, writeImpl, readWriteImpl,
                                               numAccessors,
                                               genericSigID,
                                               elemInterfaceTypeID,
                                               isIUO,
                                               overriddenID, rawAccessLevel,
                                               rawSetterAccessLevel,
                                               rawStaticSpelling, numArgNames,
                                               opaqueReturnTypeID,
                                               numVTableEntries,
                                               argNameAndDependencyIDs);
      // Resolve the name ids.
      SmallVector<Identifier, 2> argNames;
      for (auto argNameID : argNameAndDependencyIDs.slice(0, numArgNames))
         argNames.push_back(MF.getIdentifier(argNameID));
      DeclName name(ctx, DeclBaseName::createSubscript(), argNames);
      argNameAndDependencyIDs = argNameAndDependencyIDs.slice(numArgNames);

      // Exctract the accessor IDs.
      for (DeclID accessorID : argNameAndDependencyIDs.slice(0, numAccessors)) {
         accessors.IDs.push_back(accessorID);
      }
      argNameAndDependencyIDs = argNameAndDependencyIDs.slice(numAccessors);

      Expected<Decl *> overridden = MF.getDeclChecked(overriddenID);
      if (!overridden) {
         llvm::consumeError(overridden.takeError());

         DeclDeserializationError::Flags errorFlags;
         return llvm::make_error<OverrideError>(
            name, errorFlags, numVTableEntries);
      }

      for (TypeID dependencyID : argNameAndDependencyIDs) {
         auto dependency = MF.getTypeChecked(dependencyID);
         if (!dependency) {
            DeclDeserializationError::Flags errorFlags;
            return llvm::make_error<TypeError>(
               name, takeErrorInfo(dependency.takeError()),
               errorFlags, numVTableEntries);
         }
      }

      auto parent = MF.getDeclContext(contextID);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto *genericParams = MF.maybeReadGenericParams(parent);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto staticSpelling = getActualStaticSpellingKind(rawStaticSpelling);
      if (!staticSpelling.hasValue())
         MF.fatal();

      auto subscript = MF.createDecl<SubscriptDecl>(name,
                                                    SourceLoc(), *staticSpelling,
                                                    SourceLoc(), nullptr,
                                                    SourceLoc(), TypeLoc(),
                                                    parent, genericParams);
      subscript->setIsGetterMutating(isGetterMutating);
      subscript->setIsSetterMutating(isSetterMutating);
      declOrOffset = subscript;

      subscript->setGenericSignature(MF.getGenericSignature(genericSigID));

      subscript->setIndices(MF.readParameterList());

      MF.configureStorage(subscript, opaqueReadOwnership,
                          readImpl, writeImpl, readWriteImpl, accessors);

      if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
         subscript->setAccess(*accessLevel);
      else
         MF.fatal();

      if (subscript->supportsMutation()) {
         if (auto setterAccess = getActualAccessLevel(rawSetterAccessLevel))
            subscript->setSetterAccess(*setterAccess);
         else
            MF.fatal();
      }

      auto elemInterfaceType = MF.getType(elemInterfaceTypeID);
      subscript->getElementTypeLoc().setType(elemInterfaceType);
      subscript->setImplicitlyUnwrappedOptional(isIUO);

      if (isImplicit)
         subscript->setImplicit();
      subscript->setIsObjC(isObjC);
      subscript->setOverriddenDecl(cast_or_null<SubscriptDecl>(overridden.get()));
      if (subscript->getOverriddenDecl())
         AddAttribute(new (ctx) OverrideAttr(SourceLoc()));

      if (opaqueReturnTypeID) {
         ctx.evaluator.cacheOutput(
            OpaqueResultTypeRequest{subscript},
            cast<OpaqueTypeDecl>(MF.getDecl(opaqueReturnTypeID)));
      }

      return subscript;
   }

   Expected<Decl *> deserializeExtension(ArrayRef<uint64_t> scratch,
                                         StringRef blobData) {
      TypeID extendedTypeID;
      DeclID extendedNominalID;
      DeclContextID contextID;
      bool isImplicit;
      GenericSignatureID genericSigID;
      unsigned numConformances, numInherited;
      ArrayRef<uint64_t> inheritedAndDependencyIDs;

      decls_block::ExtensionLayout::readRecord(scratch, extendedTypeID,
                                               extendedNominalID, contextID,
                                               isImplicit, genericSigID,
                                               numConformances, numInherited,
                                               inheritedAndDependencyIDs);

      auto DC = MF.getDeclContext(contextID);

      for (TypeID dependencyID : inheritedAndDependencyIDs.slice(numInherited)) {
         auto dependency = MF.getTypeChecked(dependencyID);
         if (!dependency) {
            return llvm::make_error<ExtensionError>(
               takeErrorInfo(dependency.takeError()));
         }
      }

      if (declOrOffset.isComplete())
         return declOrOffset;

      auto extension = ExtensionDecl::create(ctx, SourceLoc(), nullptr, { },
                                             DC, nullptr);
      declOrOffset = extension;

      // Generic parameter lists are written from outermost to innermost.
      // Keep reading until we run out of generic parameter lists.
      GenericParamList *outerParams = nullptr;
      while (auto *genericParams = MF.maybeReadGenericParams(DC)) {
         genericParams->setOuterParameters(outerParams);

         // Set up the DeclContexts for the GenericTypeParamDecls in the list.
         for (auto param : *genericParams)
            param->setDeclContext(extension);

         outerParams = genericParams;
      }
      ctx.evaluator.cacheOutput(GenericParamListRequest{extension},
                                std::move(outerParams));

      extension->setGenericSignature(MF.getGenericSignature(genericSigID));

      auto extendedType = MF.getType(extendedTypeID);
      ctx.evaluator.cacheOutput(ExtendedTypeRequest{extension},
                                std::move(extendedType));
      auto nominal = dyn_cast<NominalTypeDecl>(MF.getDecl(extendedNominalID));
      ctx.evaluator.cacheOutput(ExtendedNominalRequest{extension},
                                std::move(nominal));

      if (isImplicit)
         extension->setImplicit();

      auto rawInheritedIDs = inheritedAndDependencyIDs.slice(0, numInherited);
      handleInherited(extension, rawInheritedIDs);

      extension->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());
      skipRecord(MF.DeclTypeCursor, decls_block::MEMBERS);
      extension->setConformanceLoader(
         &MF,
         encodeLazyConformanceContextData(numConformances,
                                          MF.DeclTypeCursor.GetCurrentBitNo()));

      nominal->addExtension(extension);

#ifndef NDEBUG
      if (outerParams) {
         unsigned paramCount = 0;
         for (auto *paramList = outerParams;
              paramList != nullptr;
              paramList = paramList->getOuterParameters()) {
            paramCount += paramList->size();
         }
         assert(paramCount ==
                extension->getGenericSignature()->getGenericParams().size());
      }
#endif

      return extension;
   }

   Expected<Decl *> deserializeDestructor(ArrayRef<uint64_t> scratch,
                                          StringRef blobData) {
      DeclContextID contextID;
      bool isImplicit, isObjC;
      GenericSignatureID genericSigID;

      decls_block::DestructorLayout::readRecord(scratch, contextID,
                                                isImplicit, isObjC,
                                                genericSigID);

      DeclContext *DC = MF.getDeclContext(contextID);
      if (declOrOffset.isComplete())
         return declOrOffset;

      auto dtor = MF.createDecl<DestructorDecl>(SourceLoc(), DC);
      declOrOffset = dtor;

      if (auto bodyText = MF.maybeReadInlinableBodyText())
         dtor->setBodyStringRepresentation(*bodyText);

      dtor->setGenericSignature(MF.getGenericSignature(genericSigID));

      dtor->setAccess(std::max(cast<ClassDecl>(DC)->getFormalAccess(),
                               AccessLevel::Internal));

      if (isImplicit)
         dtor->setImplicit();
      dtor->setIsObjC(isObjC);

      return dtor;
   }
};

Expected<Decl *>
ModuleFile::getDeclChecked(
   DeclID DID,
   llvm::function_ref<bool(DeclAttributes)> matchAttributes) {
   if (DID == 0)
      return nullptr;

   assert(DID <= Decls.size() && "invalid decl ID");
   auto &declOrOffset = Decls[DID-1];

   if (!declOrOffset.isComplete()) {
      ++NumDeclsLoaded;
      BCOffsetRAII restoreOffset(DeclTypeCursor);
      fatalIfNotSuccess(DeclTypeCursor.JumpToBit(declOrOffset));

      Expected<Decl *> deserialized =
         DeclDeserializer(*this, declOrOffset).getDeclCheckedImpl(
            matchAttributes);
      if (!deserialized)
         return deserialized;
   } else if (matchAttributes) {
      // Decl was cached but we may need to filter it
      if (!matchAttributes(declOrOffset.get()->getAttrs()))
         return llvm::make_error<DeclAttributesDidNotMatch>();
   }

   // Tag every deserialized ValueDecl coming out of getDeclChecked with its ID.
   assert(declOrOffset.isComplete());
   if (auto *IDC = dyn_cast_or_null<IterableDeclContext>(declOrOffset.get())) {
      // Only set the DeclID on the returned Decl if it's one that was loaded
      // and _wasn't_ one that had its DeclID set elsewhere (a followed XREF).
      if (IDC->wasDeserialized() &&
          static_cast<uint32_t>(IDC->getDeclID()) == 0) {
         IDC->setDeclID(DID);
      }
   }
   return declOrOffset;
}

llvm::Error DeclDeserializer::deserializeDeclAttributes() {
   using namespace decls_block;

   SmallVector<uint64_t, 64> scratch;
   StringRef blobData;
   while (true) {
      BCOffsetRAII restoreOffset(MF.DeclTypeCursor);
      llvm::BitstreamEntry entry =
         MF.fatalIfUnexpected(MF.DeclTypeCursor.advance());
      if (entry.Kind != llvm::BitstreamEntry::Record) {
         // We don't know how to serialize decls represented by sub-blocks.
         MF.fatal();
      }

      unsigned recordID = MF.fatalIfUnexpected(
         MF.DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));

      if (isDeclAttrRecord(recordID)) {
         DeclAttribute *Attr = nullptr;
         bool skipAttr = false;
         switch (recordID) {
            case decls_block::PILGenName_DECL_ATTR: {
               bool isImplicit;
               serialization::decls_block::PILGenNameDeclAttrLayout::readRecord(
                  scratch, isImplicit);
               Attr = new (ctx) PILGenNameAttr(blobData, isImplicit);
               break;
            }

            case decls_block::CDecl_DECL_ATTR: {
               bool isImplicit;
               serialization::decls_block::CDeclDeclAttrLayout::readRecord(
                  scratch, isImplicit);
               Attr = new (ctx) CDeclAttr(blobData, isImplicit);
               break;
            }

            case decls_block::Alignment_DECL_ATTR: {
               bool isImplicit;
               unsigned alignment;
               serialization::decls_block::AlignmentDeclAttrLayout::readRecord(
                  scratch, isImplicit, alignment);
               Attr = new (ctx) AlignmentAttr(alignment, SourceLoc(), SourceRange(),
                                              isImplicit);
               break;
            }

            case decls_block::SwiftNativeObjCRuntimeBase_DECL_ATTR: {
               bool isImplicit;
               IdentifierID nameID;
               serialization::decls_block::SwiftNativeObjCRuntimeBaseDeclAttrLayout
               ::readRecord(scratch, isImplicit, nameID);

               auto name = MF.getIdentifier(nameID);
               Attr = new (ctx) SwiftNativeObjCRuntimeBaseAttr(name, SourceLoc(),
                                                               SourceRange(),
                                                               isImplicit);
               break;
            }

            case decls_block::Semantics_DECL_ATTR: {
               bool isImplicit;
               serialization::decls_block::SemanticsDeclAttrLayout::readRecord(
                  scratch, isImplicit);
               Attr = new (ctx) SemanticsAttr(blobData, isImplicit);
               break;
            }

            case decls_block::Inline_DECL_ATTR: {
               unsigned kind;
               serialization::decls_block::InlineDeclAttrLayout::readRecord(
                  scratch, kind);
               Attr = new (ctx) InlineAttr((InlineKind)kind);
               break;
            }

            case decls_block::Optimize_DECL_ATTR: {
               unsigned kind;
               serialization::decls_block::OptimizeDeclAttrLayout::readRecord(
                  scratch, kind);
               Attr = new (ctx) OptimizeAttr((OptimizationMode)kind);
               break;
            }

            case decls_block::Effects_DECL_ATTR: {
               unsigned kind;
               serialization::decls_block::EffectsDeclAttrLayout::readRecord(scratch,
                                                                             kind);
               Attr = new (ctx) EffectsAttr((EffectsKind)kind);
               break;
            }
            case decls_block::OriginallyDefinedIn_DECL_ATTR: {
               bool isImplicit;
               unsigned Platform;
               DEF_VER_TUPLE_PIECES(MovedVer);
               // Decode the record, pulling the version tuple information.
               serialization::decls_block::OriginallyDefinedInDeclAttrLayout::readRecord(
                  scratch,
                  isImplicit,
                  LIST_VER_TUPLE_PIECES(MovedVer),
                  Platform);
               llvm::VersionTuple MovedVer;
               DECODE_VER_TUPLE(MovedVer)
               auto ModuleNameEnd = blobData.find('\0');
               assert(ModuleNameEnd != StringRef::npos);
               auto ModuleName = blobData.slice(0, ModuleNameEnd);
               Attr = new (ctx) OriginallyDefinedInAttr(SourceLoc(), SourceRange(),
                                                        ModuleName,
                                                        (PlatformKind)Platform,
                                                        MovedVer,
                                                        isImplicit);
               break;
            }

            case decls_block::Available_DECL_ATTR: {
               bool isImplicit;
               bool isUnavailable;
               bool isDeprecated;
               bool isPackageDescriptionVersionSpecific;
               DEF_VER_TUPLE_PIECES(Introduced);
               DEF_VER_TUPLE_PIECES(Deprecated);
               DEF_VER_TUPLE_PIECES(Obsoleted);
               unsigned platform, messageSize, renameSize;
               // Decode the record, pulling the version tuple information.
               serialization::decls_block::AvailableDeclAttrLayout::readRecord(
                  scratch, isImplicit, isUnavailable, isDeprecated,
                  isPackageDescriptionVersionSpecific,
                  LIST_VER_TUPLE_PIECES(Introduced),
                  LIST_VER_TUPLE_PIECES(Deprecated),
                  LIST_VER_TUPLE_PIECES(Obsoleted),
                  platform, messageSize, renameSize);

               StringRef message = blobData.substr(0, messageSize);
               blobData = blobData.substr(messageSize);
               StringRef rename = blobData.substr(0, renameSize);
               llvm::VersionTuple Introduced, Deprecated, Obsoleted;
               DECODE_VER_TUPLE(Introduced)
               DECODE_VER_TUPLE(Deprecated)
               DECODE_VER_TUPLE(Obsoleted)

               PlatformAgnosticAvailabilityKind platformAgnostic;
               if (isUnavailable)
                  platformAgnostic = PlatformAgnosticAvailabilityKind::Unavailable;
               else if (isDeprecated)
                  platformAgnostic = PlatformAgnosticAvailabilityKind::Deprecated;
               else if (((PlatformKind)platform) == PlatformKind::none &&
                        (!Introduced.empty() ||
                         !Deprecated.empty() ||
                         !Obsoleted.empty()))
                  platformAgnostic = isPackageDescriptionVersionSpecific ?
                                     PlatformAgnosticAvailabilityKind::PackageDescriptionVersionSpecific:
                                     PlatformAgnosticAvailabilityKind::SwiftVersionSpecific;
               else
                  platformAgnostic = PlatformAgnosticAvailabilityKind::None;

               Attr = new (ctx) AvailableAttr(
                  SourceLoc(), SourceRange(),
                  (PlatformKind)platform, message, rename,
                  Introduced, SourceRange(),
                  Deprecated, SourceRange(),
                  Obsoleted, SourceRange(),
                  platformAgnostic, isImplicit);
               break;
            }

            case decls_block::ObjC_DECL_ATTR: {
               bool isImplicit;
               bool isImplicitName;
               bool isSwift3Inferred;
               uint64_t numArgs;
               ArrayRef<uint64_t> rawPieceIDs;
               serialization::decls_block::ObjCDeclAttrLayout::readRecord(
                  scratch, isImplicit, isSwift3Inferred, isImplicitName, numArgs,
                  rawPieceIDs);

               SmallVector<Identifier, 4> pieces;
               for (auto pieceID : rawPieceIDs)
                  pieces.push_back(MF.getIdentifier(pieceID));

               if (numArgs == 0)
                  Attr = ObjCAttr::create(ctx, None, isImplicitName);
               else
                  Attr = ObjCAttr::create(ctx, ObjCSelector(ctx, numArgs-1, pieces),
                                          isImplicitName);
               Attr->setImplicit(isImplicit);
               cast<ObjCAttr>(Attr)->setSwift3Inferred(isSwift3Inferred);
               break;
            }

            case decls_block::Specialize_DECL_ATTR: {
               unsigned exported;
               SpecializeAttr::SpecializationKind specializationKind;
               unsigned specializationKindVal;
               GenericSignatureID specializedSigID;

               serialization::decls_block::SpecializeDeclAttrLayout::readRecord(
                  scratch, exported, specializationKindVal, specializedSigID);

               specializationKind = specializationKindVal
                                    ? SpecializeAttr::SpecializationKind::Partial
                                    : SpecializeAttr::SpecializationKind::Full;

               auto specializedSig = MF.getGenericSignature(specializedSigID);
               Attr = SpecializeAttr::create(ctx, SourceLoc(), SourceRange(),
                                             nullptr, exported != 0,
                                             specializationKind,
                                             specializedSig);
               break;
            }

            case decls_block::DynamicReplacement_DECL_ATTR: {
               bool isImplicit;
               uint64_t numArgs;
               ArrayRef<uint64_t> rawPieceIDs;
               DeclID replacedFunID;
               serialization::decls_block::DynamicReplacementDeclAttrLayout::
               readRecord(scratch, isImplicit, replacedFunID, numArgs, rawPieceIDs);

               auto baseName = MF.getDeclBaseName(rawPieceIDs[0]);
               SmallVector<Identifier, 4> pieces;
               for (auto pieceID : rawPieceIDs.slice(1))
                  pieces.push_back(MF.getIdentifier(pieceID));

               assert(numArgs != 0);
               assert(!isImplicit && "Need to update for implicit");
               Attr = DynamicReplacementAttr::create(
                  ctx, DeclName(ctx, baseName, ArrayRef<Identifier>(pieces)), &MF,
                  replacedFunID);
               break;
            }

            case decls_block::Custom_DECL_ATTR: {
               bool isImplicit;
               TypeID typeID;
               serialization::decls_block::CustomDeclAttrLayout::readRecord(
                  scratch, isImplicit, typeID);

               Expected<Type> deserialized = MF.getTypeChecked(typeID);
               if (!deserialized) {
                  if (deserialized.errorIsA<XRefNonLoadedModuleError>()) {
                     // A custom attribute defined behind an implementation-only import
                     // is safe to drop when it can't be deserialized.
                     // rdar://problem/56599179
                     consumeError(deserialized.takeError());
                     skipAttr = true;
                  } else
                     return deserialized.takeError();
               } else {
                  Attr = CustomAttr::create(ctx, SourceLoc(),
                                            TypeLoc::withoutLoc(deserialized.get()),
                                            isImplicit);
               }
               break;
            }

            case decls_block::ProjectedValueProperty_DECL_ATTR: {
               bool isImplicit;
               IdentifierID nameID;
               serialization::decls_block::ProjectedValuePropertyDeclAttrLayout
               ::readRecord(scratch, isImplicit, nameID);

               auto name = MF.getIdentifier(nameID);
               Attr = new (ctx) ProjectedValuePropertyAttr(
                  name, SourceLoc(), SourceRange(), isImplicit);
               break;
            }

#define SIMPLE_DECL_ATTR(NAME, CLASS, ...) \
      case decls_block::CLASS##_DECL_ATTR: { \
        bool isImplicit; \
        serialization::decls_block::CLASS##DeclAttrLayout::readRecord( \
            scratch, isImplicit); \
        Attr = new (ctx) CLASS##Attr(isImplicit); \
        break; \
      }
#include "polarphp/ast/AttrDef.h"

            default:
               // We don't know how to deserialize this kind of attribute.
               MF.fatal();
         }

         if (!skipAttr) {
            if (!Attr)
               return llvm::Error::success();

            AddAttribute(Attr);
         }

      } else if (recordID == decls_block::PRIVATE_DISCRIMINATOR) {
         IdentifierID discriminatorID;
         decls_block::PrivateDiscriminatorLayout::readRecord(scratch,
                                                             discriminatorID);
         privateDiscriminator = MF.getIdentifier(discriminatorID);

      } else if (recordID == decls_block::LOCAL_DISCRIMINATOR) {
         unsigned discriminator;
         decls_block::LocalDiscriminatorLayout::readRecord(scratch, discriminator);
         localDiscriminator = discriminator;
      } else if (recordID == decls_block::FILENAME_FOR_PRIVATE) {
         IdentifierID filenameID;
         decls_block::FilenameForPrivateLayout::readRecord(scratch, filenameID);
         filenameForPrivate = MF.getIdentifierText(filenameID);
      } else {
         return llvm::Error::success();
      }

      // Prepare to read the next record.
      restoreOffset.cancel();
      scratch.clear();
   }
}

Expected<Decl *>
DeclDeserializer::getDeclCheckedImpl(
   llvm::function_ref<bool(DeclAttributes)> matchAttributes) {

   auto attrError = deserializeDeclAttributes();
   if (attrError)
      return std::move(attrError);

   if (matchAttributes) {
      // Deserialize the full decl only if matchAttributes finds a match.
      DeclAttributes attrs = DeclAttributes();
      attrs.setRawAttributeChain(DAttrs);
      if (!matchAttributes(attrs))
         return llvm::make_error<DeclAttributesDidNotMatch>();
   }

   if (auto s = ctx.Stats)
      s->getFrontendCounters().NumDeclsDeserialized++;

   // FIXME: @_dynamicReplacement(for:) includes a reference to another decl,
   // usually in the same type, and that can result in this decl being
   // re-entrantly deserialized. If that happens, don't fail here.
   if (declOrOffset.isComplete())
      return declOrOffset;

   llvm::BitstreamEntry entry =
      MF.fatalIfUnexpected(MF.DeclTypeCursor.advance());
   if (entry.Kind != llvm::BitstreamEntry::Record) {
      // We don't know how to serialize decls represented by sub-blocks.
      MF.fatal();
   }

   SmallVector<uint64_t, 64> scratch;
   StringRef blobData;
   unsigned recordID = MF.fatalIfUnexpected(
      MF.DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));

   PrettyDeclDeserialization stackTraceEntry(
      &MF, declOrOffset, static_cast<decls_block::RecordKind>(recordID));

   switch (recordID) {
#define CASE(RECORD_NAME) \
  case decls_block::RECORD_NAME##Layout::Code: \
    return deserialize##RECORD_NAME(scratch, blobData);

      CASE(TypeAlias)
      CASE(GenericTypeParamDecl)
      CASE(AssociatedTypeDecl)
      CASE(Struct)
      CASE(Constructor)
      CASE(Var)
      CASE(Param)
      CASE(Func)
      CASE(OpaqueType)
      CASE(Accessor)
      CASE(PatternBinding)
      CASE(Interface)
      CASE(PrefixOperator)
      CASE(PostfixOperator)
      CASE(InfixOperator)
      CASE(PrecedenceGroup)
      CASE(Class)
      CASE(Enum)
      CASE(EnumElement)
      CASE(Subscript)
      CASE(Extension)
      CASE(Destructor)
#undef CASE

      case decls_block::XREF: {
         assert(DAttrs == nullptr);
         ModuleID baseModuleID;
         uint32_t pathLen;
         decls_block::XRefLayout::readRecord(scratch, baseModuleID, pathLen);
         auto resolved = MF.resolveCrossReference(baseModuleID, pathLen);
         if (resolved)
            declOrOffset = resolved.get();
         return resolved;
      }

      default:
         // We don't know how to deserialize this kind of decl.
         MF.fatal();
   }
}

/// Translate from the Serialization function type repr enum values to the AST
/// strongly-typed enum.
///
/// The former is guaranteed to be stable, but may not reflect this version of
/// the AST.
static Optional<polar::FunctionType::Representation>
getActualFunctionTypeRepresentation(uint8_t rep) {
   switch (rep) {
#define CASE(THE_CC) \
  case (uint8_t)serialization::FunctionTypeRepresentation::THE_CC: \
    return polar::FunctionType::Representation::THE_CC;
      CASE(Swift)
      CASE(Block)
      CASE(Thin)
      CASE(CFunctionPointer)
#undef CASE
      default:
         return None;
   }
}

/// Translate from the Serialization differentiability kind enum values to the
/// AST strongly-typed enum.
///
/// The former is guaranteed to be stable, but may not reflect this version of
/// the AST.
static Optional<polar::DifferentiabilityKind>
getActualDifferentiabilityKind(uint8_t rep) {
   switch (rep) {
#define CASE(THE_CC) \
  case (uint8_t)serialization::DifferentiabilityKind::THE_CC: \
    return polar::DifferentiabilityKind::THE_CC;
      CASE(NonDifferentiable)
      CASE(Normal)
      CASE(Linear)
#undef CASE
      default:
         return None;
   }
}

/// Translate from the Serialization function type repr enum values to the AST
/// strongly-typed enum.
///
/// The former is guaranteed to be stable, but may not reflect this version of
/// the AST.
static Optional<polar::PILFunctionType::Representation>
getActualPILFunctionTypeRepresentation(uint8_t rep) {
   switch (rep) {
#define CASE(THE_CC) \
  case (uint8_t)serialization::PILFunctionTypeRepresentation::THE_CC: \
    return polar::PILFunctionType::Representation::THE_CC;
      CASE(Thick)
      CASE(Block)
      CASE(Thin)
      CASE(CFunctionPointer)
      CASE(Method)
      CASE(ObjCMethod)
      CASE(WitnessMethod)
#undef CASE
      default:
         return None;
   }
}

/// Translate from the Serialization coroutine kind enum values to the AST
/// strongly-typed enum.
///
/// The former is guaranteed to be stable, but may not reflect this version of
/// the AST.
static Optional<polar::PILCoroutineKind>
getActualPILCoroutineKind(uint8_t rep) {
   switch (rep) {
#define CASE(KIND) \
  case (uint8_t)serialization::PILCoroutineKind::KIND: \
    return polar::PILCoroutineKind::KIND;
      CASE(None)
      CASE(YieldOnce)
      CASE(YieldMany)
#undef CASE
      default:
         return None;
   }
}

/// Translate from the serialization ReferenceOwnership enumerators, which are
/// guaranteed to be stable, to the AST ones.
static Optional<polar::ReferenceOwnership>
getActualReferenceOwnership(serialization::ReferenceOwnership raw) {
   switch (raw) {
      case serialization::ReferenceOwnership::Strong:
         return polar::ReferenceOwnership::Strong;
#define REF_STORAGE(Name, ...) \
  case serialization::ReferenceOwnership::Name: \
    return polar::ReferenceOwnership::Name;
#include "polarphp/ast/ReferenceStorageDef.h"
   }
   return None;
}

/// Translate from the serialization ValueOwnership enumerators, which are
/// guaranteed to be stable, to the AST ones.
static Optional<polar::ValueOwnership>
getActualValueOwnership(serialization::ValueOwnership raw) {
   switch (raw) {
#define CASE(ID) \
  case serialization::ValueOwnership::ID: \
    return polar::ValueOwnership::ID;
      CASE(Default)
      CASE(InOut)
      CASE(Shared)
      CASE(Owned)
#undef CASE
   }
   return None;
}

/// Translate from the serialization ParameterConvention enumerators,
/// which are guaranteed to be stable, to the AST ones.
static
Optional<polar::ParameterConvention> getActualParameterConvention(uint8_t raw) {
   switch (serialization::ParameterConvention(raw)) {
#define CASE(ID) \
  case serialization::ParameterConvention::ID: \
    return polar::ParameterConvention::ID;
      CASE(Indirect_In)
      CASE(Indirect_Inout)
      CASE(Indirect_InoutAliasable)
      CASE(Indirect_In_Guaranteed)
      CASE(Indirect_In_Constant)
      CASE(Direct_Owned)
      CASE(Direct_Unowned)
      CASE(Direct_Guaranteed)
#undef CASE
   }
   return None;
}

/// Translate from the serialization ResultConvention enumerators,
/// which are guaranteed to be stable, to the AST ones.
static
Optional<polar::ResultConvention> getActualResultConvention(uint8_t raw) {
   switch (serialization::ResultConvention(raw)) {
#define CASE(ID) \
  case serialization::ResultConvention::ID: return polar::ResultConvention::ID;
      CASE(Indirect)
      CASE(Owned)
      CASE(Unowned)
      CASE(UnownedInnerPointer)
      CASE(Autoreleased)
#undef CASE
   }
   return None;
}

Type ModuleFile::getType(TypeID TID) {
   Expected<Type> deserialized = getTypeChecked(TID);
   if (!deserialized) {
      fatal(deserialized.takeError());
   }
   return deserialized.get();
}

class polar::TypeDeserializer {
   using TypeID = serialization::TypeID;

   ModuleFile &MF;
   AstContext &ctx;
public:
   explicit TypeDeserializer(ModuleFile &MF)
      : MF(MF), ctx(MF.getContext()) {}

   Expected<Type> getTypeCheckedImpl();

   Expected<Type> deserializeBuiltinAliasType(ArrayRef<uint64_t> scratch,
                                              StringRef blobData) {
      DeclID underlyingID;
      TypeID canonicalTypeID;
      decls_block::BuiltinAliasTypeLayout::readRecord(scratch, underlyingID,
                                                      canonicalTypeID);
      auto aliasOrError = MF.getDeclChecked(underlyingID);
      if (!aliasOrError)
         return aliasOrError.takeError();
      auto alias = dyn_cast<TypeAliasDecl>(aliasOrError.get());

      if (ctx.LangOpts.EnableDeserializationRecovery) {
         Expected<Type> expectedType = MF.getTypeChecked(canonicalTypeID);
         if (!expectedType)
            return expectedType.takeError();
         if (expectedType.get()) {
            if (!alias ||
                !alias->getDeclaredInterfaceType()->isEqual(expectedType.get())) {
               // Fall back to the canonical type.
               return expectedType.get();
            }
         }
      }

      // Look through compatibility aliases that are now unavailable.
      if (alias->getAttrs().isUnavailable(ctx) &&
          alias->isCompatibilityAlias()) {
         return alias->getUnderlyingType();
      }

      return alias->getDeclaredInterfaceType();
   }

   Expected<Type> deserializeTypeAliasType(ArrayRef<uint64_t> scratch,
                                           StringRef blobData) {
      DeclID typealiasID;
      TypeID parentTypeID;
      TypeID underlyingTypeID;
      TypeID substitutedTypeID;
      SubstitutionMapID substitutionsID;
      decls_block::TypeAliasTypeLayout::readRecord(scratch, typealiasID,
                                                   parentTypeID,
                                                   underlyingTypeID,
                                                   substitutedTypeID,
                                                   substitutionsID);

      TypeAliasDecl *alias = nullptr;
      Type underlyingType;
      if (ctx.LangOpts.EnableDeserializationRecovery) {
         auto underlyingTypeOrError = MF.getTypeChecked(underlyingTypeID);
         if (!underlyingTypeOrError) {
            // If we can't deserialize the underlying type, we can't be sure the
            // actual typealias hasn't changed.
            return underlyingTypeOrError.takeError();
         }

         underlyingType = underlyingTypeOrError.get();

         if (auto aliasOrError = MF.getDeclChecked(typealiasID)) {
            alias = dyn_cast<TypeAliasDecl>(aliasOrError.get());
         } else {
            // We're going to recover by falling back to the underlying type, so
            // just ignore the error.
            llvm::consumeError(aliasOrError.takeError());
         }

         if (!alias ||
             !alias->getDeclaredInterfaceType()->isEqual(underlyingType)) {
            // Fall back to the canonical type.
            return underlyingType;
         }

      } else {
         alias = dyn_cast<TypeAliasDecl>(MF.getDecl(typealiasID));
         underlyingType = MF.getType(underlyingTypeID);
      }

      // Read the substituted type.
      auto substitutedTypeOrError = MF.getTypeChecked(substitutedTypeID);
      if (!substitutedTypeOrError)
         return substitutedTypeOrError.takeError();

      auto substitutedType = substitutedTypeOrError.get();

      // Read the substitutions.
      auto subMap = MF.getSubstitutionMap(substitutionsID);

      auto parentTypeOrError = MF.getTypeChecked(parentTypeID);
      if (!parentTypeOrError)
         return underlyingType;

      // Look through compatibility aliases that are now unavailable.
      if (alias &&
          alias->getAttrs().isUnavailable(ctx) &&
          alias->isCompatibilityAlias()) {
         return alias->getUnderlyingType().subst(subMap);
      }

      auto parentType = parentTypeOrError.get();
      return TypeAliasType::get(alias, parentType, subMap, substitutedType);
   }

   Expected<Type> deserializeNominalType(ArrayRef<uint64_t> scratch,
                                         StringRef blobData) {
      DeclID declID;
      TypeID parentID;
      decls_block::NominalTypeLayout::readRecord(scratch, declID, parentID);

      Expected<Type> parentTy = MF.getTypeChecked(parentID);
      if (!parentTy)
         return parentTy.takeError();

      auto nominalOrError = MF.getDeclChecked(declID);
      if (!nominalOrError)
         return nominalOrError.takeError();

      // Look through compatibility aliases.
      if (auto *alias = dyn_cast<TypeAliasDecl>(nominalOrError.get())) {
         // Reminder: TypeBase::getAs will look through sugar. But we don't want to
         // do that here, so we do isa<> checks on the TypeBase itself instead of
         // using the Type wrapper.
         const TypeBase *underlyingTy = nullptr;
         while (alias->isCompatibilityAlias()) {
            underlyingTy = alias->getUnderlyingType().getPointer();

            // If the underlying type is itself a typealias, it might be another
            // compatibility alias, meaning we need to go around the loop again.
            auto aliasTy = dyn_cast<TypeAliasType>(underlyingTy);
            if (!aliasTy)
               break;
            alias = aliasTy->getDecl();
         }

         // We only want to use the type we found if it's a simple non-generic
         // nominal type.
         if (auto simpleNominalTy = dyn_cast_or_null<NominalType>(underlyingTy)) {
            nominalOrError = simpleNominalTy->getDecl();
            (void)!nominalOrError; // "Check" the llvm::Expected<> value.
         }
      }

      auto nominal = dyn_cast<NominalTypeDecl>(nominalOrError.get());
      if (!nominal) {
         XRefTracePath tinyTrace{*nominalOrError.get()->getModuleContext()};
         DeclName fullName = cast<ValueDecl>(nominalOrError.get())->getFullName();
         tinyTrace.addValue(fullName.getBaseIdentifier());
         return llvm::make_error<XRefError>("declaration is not a nominal type",
                                            tinyTrace, fullName);
      }
      return NominalType::get(nominal, parentTy.get(), ctx);
   }

   Expected<Type> deserializeParenType(ArrayRef<uint64_t> scratch,
                                       StringRef blobData) {
      TypeID underlyingID;
      decls_block::ParenTypeLayout::readRecord(scratch, underlyingID);

      auto underlyingTy = MF.getTypeChecked(underlyingID);
      if (!underlyingTy)
         return underlyingTy.takeError();

      return ParenType::get(ctx, underlyingTy.get());
   }

   Expected<Type> deserializeTupleType(SmallVectorImpl<uint64_t> &scratch,
                                       StringRef blobData) {
      // The tuple record itself is empty. Read all trailing elements.
      SmallVector<TupleTypeElt, 8> elements;
      while (true) {
         llvm::BitstreamEntry entry =
            MF.fatalIfUnexpected(MF.DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
         if (entry.Kind != llvm::BitstreamEntry::Record)
            break;

         scratch.clear();
         unsigned recordID = MF.fatalIfUnexpected(
            MF.DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
         if (recordID != decls_block::TUPLE_TYPE_ELT)
            break;

         IdentifierID nameID;
         TypeID typeID;
         decls_block::TupleTypeEltLayout::readRecord(scratch, nameID, typeID);

         auto elementTy = MF.getTypeChecked(typeID);
         if (!elementTy)
            return elementTy.takeError();

         elements.emplace_back(elementTy.get(), MF.getIdentifier(nameID));
      }

      return TupleType::get(elements, ctx);
   }

   Expected<Type> deserializeAnyFunctionType(SmallVectorImpl<uint64_t> &scratch,
                                             StringRef blobData,
                                             bool isGeneric) {
      TypeID resultID;
      uint8_t rawRepresentation, rawDiffKind;
      bool noescape = false, throws;
      GenericSignature genericSig = GenericSignature();
      clang::Type *clangFunctionType = nullptr;

      // FIXME: [clang-function-type-serialization] Deserialize a clang::Type out
      // of the record.
      if (!isGeneric) {
         decls_block::FunctionTypeLayout::readRecord(
            scratch, resultID, rawRepresentation, noescape, throws, rawDiffKind);
      } else {
         GenericSignatureID rawGenericSig;
         decls_block::GenericFunctionTypeLayout::readRecord(
            scratch, resultID, rawRepresentation, throws, rawDiffKind,
            rawGenericSig);
         genericSig = MF.getGenericSignature(rawGenericSig);
      }

      auto representation = getActualFunctionTypeRepresentation(rawRepresentation);
      if (!representation.hasValue())
         MF.fatal();

      auto diffKind = getActualDifferentiabilityKind(rawDiffKind);
      if (!diffKind.hasValue())
         MF.fatal();

      auto info = FunctionType::ExtInfo(*representation, noescape, throws,
                                        *diffKind, clangFunctionType);


      auto resultTy = MF.getTypeChecked(resultID);
      if (!resultTy)
         return resultTy.takeError();

      SmallVector<AnyFunctionType::Param, 8> params;
      while (true) {
         llvm::BitstreamEntry entry =
            MF.fatalIfUnexpected(MF.DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
         if (entry.Kind != llvm::BitstreamEntry::Record)
            break;

         scratch.clear();
         unsigned recordID = MF.fatalIfUnexpected(
            MF.DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
         if (recordID != decls_block::FUNCTION_PARAM)
            break;

         IdentifierID labelID;
         TypeID typeID;
         bool isVariadic, isAutoClosure, isNonEphemeral;
         unsigned rawOwnership;
         decls_block::FunctionParamLayout::readRecord(scratch, labelID, typeID,
                                                      isVariadic, isAutoClosure,
                                                      isNonEphemeral,
                                                      rawOwnership);

         auto ownership =
            getActualValueOwnership((serialization::ValueOwnership)rawOwnership);
         if (!ownership)
            MF.fatal();

         auto paramTy = MF.getTypeChecked(typeID);
         if (!paramTy)
            return paramTy.takeError();

         params.emplace_back(paramTy.get(),
                             MF.getIdentifier(labelID),
                             ParameterTypeFlags(isVariadic, isAutoClosure,
                                                isNonEphemeral, *ownership));
      }

      if (!isGeneric) {
         assert(genericSig.isNull());
         return FunctionType::get(params, resultTy.get(), info);
      }

      assert(!genericSig.isNull());
      return GenericFunctionType::get(genericSig, params, resultTy.get(), info);
   }

   Expected<Type> deserializeFunctionType(SmallVectorImpl<uint64_t> &scratch,
                                          StringRef blobData) {
      return deserializeAnyFunctionType(scratch, blobData, /*isGeneric*/false);
   }

   Expected<Type>
   deserializeGenericFunctionType(SmallVectorImpl<uint64_t> &scratch,
                                  StringRef blobData) {
      return deserializeAnyFunctionType(scratch, blobData, /*isGeneric*/true);
   }

   template <typename Layout, typename ASTType, bool CanBeThin>
   Expected<Type> deserializeAnyMetatypeType(ArrayRef<uint64_t> scratch,
                                             StringRef blobData) {
      TypeID instanceID;
      uint8_t repr;
      Layout::readRecord(scratch, instanceID, repr);

      auto instanceType = MF.getTypeChecked(instanceID);
      if (!instanceType)
         return instanceType.takeError();

      switch (repr) {
         case serialization::MetatypeRepresentation::MR_None:
            return ASTType::get(instanceType.get());

         case serialization::MetatypeRepresentation::MR_Thin:
            if (!CanBeThin)
               MF.fatal();
            return ASTType::get(instanceType.get(),
                                MetatypeRepresentation::Thin);

         case serialization::MetatypeRepresentation::MR_Thick:
            return ASTType::get(instanceType.get(),
                                MetatypeRepresentation::Thick);

         case serialization::MetatypeRepresentation::MR_ObjC:
            return ASTType::get(instanceType.get(),
                                MetatypeRepresentation::ObjC);

         default:
            MF.fatal();
      }
   }

   Expected<Type>
   deserializeExistentialMetatypeType(ArrayRef<uint64_t> scratch,
                                      StringRef blobData) {
      return
         deserializeAnyMetatypeType<decls_block::ExistentialMetatypeTypeLayout,
            ExistentialMetatypeType, /*CanBeThin*/false>(
            scratch, blobData);
   }

   Expected<Type> deserializeMetatypeType(ArrayRef<uint64_t> scratch,
                                          StringRef blobData) {
      return deserializeAnyMetatypeType<decls_block::MetatypeTypeLayout,
         MetatypeType, /*CanBeThin*/true>(
         scratch, blobData);
   }

   Expected<Type> deserializeDynamicSelfType(ArrayRef<uint64_t> scratch,
                                             StringRef blobData) {
      TypeID selfID;
      decls_block::DynamicSelfTypeLayout::readRecord(scratch, selfID);
      return DynamicSelfType::get(MF.getType(selfID), ctx);
   }

   Expected<Type> deserializeReferenceStorageType(ArrayRef<uint64_t> scratch,
                                                  StringRef blobData) {
      uint8_t rawOwnership;
      TypeID objectTypeID;
      decls_block::ReferenceStorageTypeLayout::readRecord(scratch, rawOwnership,
                                                          objectTypeID);

      auto ownership = getActualReferenceOwnership(
         (serialization::ReferenceOwnership)rawOwnership);
      if (!ownership.hasValue())
         MF.fatal();

      auto objectTy = MF.getTypeChecked(objectTypeID);
      if (!objectTy)
         return objectTy.takeError();

      return ReferenceStorageType::get(objectTy.get(), ownership.getValue(), ctx);
   }

   Expected<Type> deserializePrimaryArchetypeType(ArrayRef<uint64_t> scratch,
                                                  StringRef blobData) {
      GenericSignatureID sigID;
      unsigned depth, index;

      decls_block::PrimaryArchetypeTypeLayout::readRecord(scratch, sigID,
                                                          depth, index);

      auto sig = MF.getGenericSignature(sigID);
      if (!sig)
         MF.fatal();

      Type interfaceType = GenericTypeParamType::get(depth, index, ctx);
      Type contextType = sig->getGenericEnvironment()
         ->mapTypeIntoContext(interfaceType);

      if (contextType->hasError())
         MF.fatal();

      return contextType;
   }

   Expected<Type> deserializeOpenedArchetypeType(ArrayRef<uint64_t> scratch,
                                                 StringRef blobData) {
      TypeID existentialID;

      decls_block::OpenedArchetypeTypeLayout::readRecord(scratch,
                                                         existentialID);

      return OpenedArchetypeType::get(MF.getType(existentialID));
   }

   Expected<Type> deserializeOpaqueArchetypeType(ArrayRef<uint64_t> scratch,
                                                 StringRef blobData) {
      DeclID opaqueDeclID;
      SubstitutionMapID subsID;
      decls_block::OpaqueArchetypeTypeLayout::readRecord(scratch,
                                                         opaqueDeclID, subsID);

      auto opaqueDecl = cast<OpaqueTypeDecl>(MF.getDecl(opaqueDeclID));
      auto subs = MF.getSubstitutionMap(subsID);

      return OpaqueTypeArchetypeType::get(opaqueDecl, subs);
   }

   Expected<Type> deserializeNestedArchetypeType(ArrayRef<uint64_t> scratch,
                                                 StringRef blobData) {
      TypeID rootID, interfaceTyID;
      decls_block::NestedArchetypeTypeLayout::readRecord(scratch,
                                                         rootID, interfaceTyID);

      auto rootTy = MF.getType(rootID)->castTo<ArchetypeType>();
      auto interfaceTy = MF.getType(interfaceTyID)->castTo<DependentMemberType>();
      return rootTy->getGenericEnvironment()->mapTypeIntoContext(interfaceTy);
   }

   Expected<Type> deserializeGenericTypeParamType(ArrayRef<uint64_t> scratch,
                                                  StringRef blobData) {
      DeclID declIDOrDepth;
      unsigned indexPlusOne;

      decls_block::GenericTypeParamTypeLayout::readRecord(scratch, declIDOrDepth,
                                                          indexPlusOne);

      if (indexPlusOne == 0) {
         auto genericParam
            = dyn_cast_or_null<GenericTypeParamDecl>(MF.getDecl(declIDOrDepth));

         if (!genericParam)
            MF.fatal();

         return genericParam->getDeclaredInterfaceType();
      }

      return GenericTypeParamType::get(declIDOrDepth,indexPlusOne-1,ctx);
   }

   Expected<Type> deserializeInterfaceCompositionType(ArrayRef<uint64_t> scratch,
                                                     StringRef blobData) {
      bool hasExplicitAnyObject;
      ArrayRef<uint64_t> rawInterfaceIDs;

      decls_block::InterfaceCompositionTypeLayout::readRecord(scratch,
                                                             hasExplicitAnyObject,
                                                             rawInterfaceIDs);
      SmallVector<Type, 4> protocols;
      for (TypeID protoID : rawInterfaceIDs) {
         auto protoTy = MF.getTypeChecked(protoID);
         if (!protoTy)
            return protoTy.takeError();
         protocols.push_back(protoTy.get());
      }

      return InterfaceCompositionType::get(ctx, protocols, hasExplicitAnyObject);
   }

   Expected<Type> deserializeDependentMemberType(ArrayRef<uint64_t> scratch,
                                                 StringRef blobData) {
      TypeID baseID;
      DeclID assocTypeID;

      decls_block::DependentMemberTypeLayout::readRecord(scratch, baseID,
                                                         assocTypeID);
      auto assocType = MF.getDeclChecked(assocTypeID);
      if (!assocType)
         return assocType.takeError();

      return DependentMemberType::get(
         MF.getType(baseID),
         cast<AssociatedTypeDecl>(assocType.get()));
   }

   Expected<Type> deserializeBoundGenericType(ArrayRef<uint64_t> scratch,
                                              StringRef blobData) {
      DeclID declID;
      TypeID parentID;
      ArrayRef<uint64_t> rawArgumentIDs;

      decls_block::BoundGenericTypeLayout::readRecord(scratch, declID, parentID,
                                                      rawArgumentIDs);

      auto nominalOrError = MF.getDeclChecked(declID);
      if (!nominalOrError)
         return nominalOrError.takeError();
      auto nominal = cast<NominalTypeDecl>(nominalOrError.get());

      // FIXME: Check this?
      auto parentTy = MF.getType(parentID);

      SmallVector<Type, 8> genericArgs;
      for (TypeID ID : rawArgumentIDs) {
         auto argTy = MF.getTypeChecked(ID);
         if (!argTy)
            return argTy.takeError();

         genericArgs.push_back(argTy.get());
      }

      return BoundGenericType::get(nominal, parentTy, genericArgs);
   }

   Expected<Type> deserializePILBlockStorageType(ArrayRef<uint64_t> scratch,
                                                 StringRef blobData) {
      TypeID captureID;
      decls_block::PILBlockStorageTypeLayout::readRecord(scratch, captureID);
      return PILBlockStorageType::get(MF.getType(captureID)->getCanonicalType());
   }

   Expected<Type> deserializePILBoxType(ArrayRef<uint64_t> scratch,
                                        StringRef blobData) {
      PILLayoutID layoutID;
      SubstitutionMapID subMapID;
      decls_block::PILBoxTypeLayout::readRecord(scratch, layoutID, subMapID);

      // Get the layout.
      auto getLayout = [this](PILLayoutID layoutID) -> PILLayout * {
         assert(layoutID > 0 && layoutID <= MF.PILLayouts.size()
                && "invalid layout ID");

         auto &layoutOrOffset = MF.PILLayouts[layoutID - 1];
         if (layoutOrOffset.isComplete()) {
            return layoutOrOffset;
         }

         BCOffsetRAII saveOffset(MF.DeclTypeCursor);
         MF.fatalIfNotSuccess(MF.DeclTypeCursor.JumpToBit(layoutOrOffset));
         auto layout = MF.readPILLayout(MF.DeclTypeCursor);
         if (!layout)
            MF.fatal();
         layoutOrOffset = layout;
         return layout;
      };

      auto layout = getLayout(layoutID);
      if (!layout)
         return nullptr;

      auto subMap = MF.getSubstitutionMap(subMapID);
      return PILBoxType::get(ctx, layout, subMap);
   }

   Expected<Type> deserializePILFunctionType(ArrayRef<uint64_t> scratch,
                                             StringRef blobData) {
      uint8_t rawCoroutineKind;
      uint8_t rawCalleeConvention;
      uint8_t rawRepresentation;
      uint8_t rawDiffKind;
      bool pseudogeneric = false;
      bool noescape;
      bool hasErrorResult;
      unsigned numParams;
      unsigned numYields;
      unsigned numResults;
      GenericSignatureID rawGenericSig;
      ArrayRef<uint64_t> variableData;
      clang::FunctionType *clangFunctionType = nullptr;

      // FIXME: [clang-function-type-serialization] Deserialize a
      // clang::FunctionType out of the record.
      decls_block::PILFunctionTypeLayout::readRecord(scratch,
                                                     rawCoroutineKind,
                                                     rawCalleeConvention,
                                                     rawRepresentation,
                                                     pseudogeneric,
                                                     noescape,
                                                     rawDiffKind,
                                                     hasErrorResult,
                                                     numParams,
                                                     numYields,
                                                     numResults,
                                                     rawGenericSig,
                                                     variableData);

      // Process the ExtInfo.
      auto representation
         = getActualPILFunctionTypeRepresentation(rawRepresentation);
      if (!representation.hasValue())
         MF.fatal();

      auto diffKind = getActualDifferentiabilityKind(rawDiffKind);
      if (!diffKind.hasValue())
         MF.fatal();

      PILFunctionType::ExtInfo extInfo(*representation, pseudogeneric, noescape,
                                       *diffKind, clangFunctionType);

      // Process the coroutine kind.
      auto coroutineKind = getActualPILCoroutineKind(rawCoroutineKind);
      if (!coroutineKind.hasValue())
         MF.fatal();

      // Process the callee convention.
      auto calleeConvention = getActualParameterConvention(rawCalleeConvention);
      if (!calleeConvention.hasValue())
         MF.fatal();

      auto processParameter = [&](TypeID typeID, uint64_t rawConvention)
         -> llvm::Expected<PILParameterInfo> {
         auto convention = getActualParameterConvention(rawConvention);
         if (!convention)
            MF.fatal();
         auto type = MF.getTypeChecked(typeID);
         if (!type)
            return type.takeError();
         return PILParameterInfo(type.get()->getCanonicalType(), *convention);
      };

      auto processYield = [&](TypeID typeID, uint64_t rawConvention)
         -> llvm::Expected<PILYieldInfo> {
         auto convention = getActualParameterConvention(rawConvention);
         if (!convention)
            MF.fatal();
         auto type = MF.getTypeChecked(typeID);
         if (!type)
            return type.takeError();
         return PILYieldInfo(type.get()->getCanonicalType(), *convention);
      };

      auto processResult = [&](TypeID typeID, uint64_t rawConvention)
         -> llvm::Expected<PILResultInfo> {
         auto convention = getActualResultConvention(rawConvention);
         if (!convention)
            MF.fatal();
         auto type = MF.getTypeChecked(typeID);
         if (!type)
            return type.takeError();
         return PILResultInfo(type.get()->getCanonicalType(), *convention);
      };

      // Bounds check.  FIXME: overflow
      if (2 * numParams + 2 * numResults + 2 * unsigned(hasErrorResult)
          > variableData.size()) {
         MF.fatal();
      }

      unsigned nextVariableDataIndex = 0;

      // Process the parameters.
      SmallVector<PILParameterInfo, 8> allParams;
      allParams.reserve(numParams);
      for (unsigned i = 0; i != numParams; ++i) {
         auto typeID = variableData[nextVariableDataIndex++];
         auto rawConvention = variableData[nextVariableDataIndex++];
         auto param = processParameter(typeID, rawConvention);
         if (!param)
            return param.takeError();
         allParams.push_back(param.get());
      }

      // Process the yields.
      SmallVector<PILYieldInfo, 8> allYields;
      allYields.reserve(numYields);
      for (unsigned i = 0; i != numYields; ++i) {
         auto typeID = variableData[nextVariableDataIndex++];
         auto rawConvention = variableData[nextVariableDataIndex++];
         auto yield = processYield(typeID, rawConvention);
         if (!yield)
            return yield.takeError();
         allYields.push_back(yield.get());
      }

      // Process the results.
      SmallVector<PILResultInfo, 8> allResults;
      allParams.reserve(numResults);
      for (unsigned i = 0; i != numResults; ++i) {
         auto typeID = variableData[nextVariableDataIndex++];
         auto rawConvention = variableData[nextVariableDataIndex++];
         auto result = processResult(typeID, rawConvention);
         if (!result)
            return result.takeError();
         allResults.push_back(result.get());
      }

      // Process the error result.
      Optional<PILResultInfo> errorResult;
      if (hasErrorResult) {
         auto typeID = variableData[nextVariableDataIndex++];
         auto rawConvention = variableData[nextVariableDataIndex++];
         auto maybeErrorResult = processResult(typeID, rawConvention);
         if (!maybeErrorResult)
            return maybeErrorResult.takeError();
         errorResult = maybeErrorResult.get();
      }

      InterfaceConformanceRef witnessMethodConformance;
      if (*representation == PILFunctionTypeRepresentation::WitnessMethod) {
         witnessMethodConformance = MF.readConformance(MF.DeclTypeCursor);
      }

      GenericSignature genericSig = MF.getGenericSignature(rawGenericSig);
      return PILFunctionType::get(genericSig, extInfo, coroutineKind.getValue(),
                                  calleeConvention.getValue(),
                                  allParams, allYields, allResults,
                                  errorResult,
                                  SubstitutionMap(), false,
                                  ctx, witnessMethodConformance);
   }

   Expected<Type> deserializeArraySliceType(ArrayRef<uint64_t> scratch,
                                            StringRef blobData) {
      TypeID baseID;
      decls_block::ArraySliceTypeLayout::readRecord(scratch, baseID);

      auto baseTy = MF.getTypeChecked(baseID);
      if (!baseTy)
         return baseTy.takeError();

      return ArraySliceType::get(baseTy.get());
   }

   Expected<Type> deserializeDictionaryType(ArrayRef<uint64_t> scratch,
                                            StringRef blobData) {
      TypeID keyID, valueID;
      decls_block::DictionaryTypeLayout::readRecord(scratch, keyID, valueID);

      auto keyTy = MF.getTypeChecked(keyID);
      if (!keyTy)
         return keyTy.takeError();

      auto valueTy = MF.getTypeChecked(valueID);
      if (!valueTy)
         return valueTy.takeError();

      return DictionaryType::get(keyTy.get(), valueTy.get());
   }

   Expected<Type> deserializeOptionalType(ArrayRef<uint64_t> scratch,
                                          StringRef blobData) {
      TypeID baseID;
      decls_block::OptionalTypeLayout::readRecord(scratch, baseID);

      auto baseTy = MF.getTypeChecked(baseID);
      if (!baseTy)
         return baseTy.takeError();

      return OptionalType::get(baseTy.get());
   }

   Expected<Type> deserializeUnboundGenericType(ArrayRef<uint64_t> scratch,
                                                StringRef blobData) {
      DeclID genericID;
      TypeID parentID;
      decls_block::UnboundGenericTypeLayout::readRecord(scratch,
                                                        genericID, parentID);

      auto nominalOrError = MF.getDeclChecked(genericID);
      if (!nominalOrError)
         return nominalOrError.takeError();
      auto genericDecl = cast<GenericTypeDecl>(nominalOrError.get());

      // FIXME: Check this?
      auto parentTy = MF.getType(parentID);

      return UnboundGenericType::get(genericDecl, parentTy, ctx);
   }
};

Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
   if (TID == 0)
      return Type();

   assert(TID <= Types.size() && "invalid type ID");
   auto &typeOrOffset = Types[TID-1];

   if (typeOrOffset.isComplete())
      return typeOrOffset;

   BCOffsetRAII restoreOffset(DeclTypeCursor);
   fatalIfNotSuccess(DeclTypeCursor.JumpToBit(typeOrOffset));

   auto result = TypeDeserializer(*this).getTypeCheckedImpl();
   if (!result)
      return result;
   typeOrOffset = result.get();

#ifndef NDEBUG
   PrettyStackTraceType trace(getContext(), "deserializing", typeOrOffset.get());
   if (typeOrOffset.get()->hasError()) {
      typeOrOffset.get()->dump(llvm::errs());
      llvm_unreachable("deserialization produced an invalid type "
                       "(rdar://problem/30382791)");
   }
#endif

   // Invoke the callback on the deserialized type.
   DeserializedTypeCallback(typeOrOffset.get());
   return typeOrOffset.get();
}

Expected<Type> TypeDeserializer::getTypeCheckedImpl() {
   if (auto s = ctx.Stats)
      s->getFrontendCounters().NumTypesDeserialized++;

   llvm::BitstreamEntry entry =
      MF.fatalIfUnexpected(MF.DeclTypeCursor.advance());

   if (entry.Kind != llvm::BitstreamEntry::Record) {
      // We don't know how to serialize types represented by sub-blocks.
      MF.fatal();
   }

   SmallVector<uint64_t, 64> scratch;
   StringRef blobData;
   unsigned recordID = MF.fatalIfUnexpected(
      MF.DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));

   switch (recordID) {
#define CASE(RECORD_NAME) \
  case decls_block::RECORD_NAME##TypeLayout::Code: \
    return deserialize##RECORD_NAME##Type(scratch, blobData);

      CASE(BuiltinAlias)
      CASE(TypeAlias)
      CASE(Nominal)
      CASE(Paren)
      CASE(Tuple)
      CASE(Function)
      CASE(GenericFunction)
      CASE(ExistentialMetatype)
      CASE(Metatype)
      CASE(DynamicSelf)
      CASE(ReferenceStorage)
      CASE(PrimaryArchetype)
      CASE(OpaqueArchetype)
      CASE(OpenedArchetype)
      CASE(NestedArchetype)
      CASE(GenericTypeParam)
      CASE(InterfaceComposition)
      CASE(DependentMember)
      CASE(BoundGeneric)
      CASE(PILBlockStorage)
      CASE(PILBox)
      CASE(PILFunction)
      CASE(ArraySlice)
      CASE(Dictionary)
      CASE(Optional)
      CASE(UnboundGeneric)

#undef CASE

      default:
         // We don't know how to deserialize this kind of type.
         MF.fatal();
   }
}

Decl *handleErrorAndSupplyMissingClassMember(AstContext &context,
                                             llvm::Error &&error,
                                             ClassDecl *containingClass) {
   Decl *suppliedMissingMember = nullptr;
   auto handleMissingClassMember = [&](const DeclDeserializationError &error) {
      if (error.isDesignatedInitializer())
         containingClass->setHasMissingDesignatedInitializers();
      if (error.getNumberOfVTableEntries() > 0)
         containingClass->setHasMissingVTableEntries();

      suppliedMissingMember = MissingMemberDecl::create(
         context, containingClass, error.getName(),
         error.getNumberOfVTableEntries(),
         error.needsFieldOffsetVectorEntry());
   };
   llvm::handleAllErrors(std::move(error), handleMissingClassMember);
   return suppliedMissingMember;
}

Decl *handleErrorAndSupplyMissingProtoMember(AstContext &context,
                                             llvm::Error &&error,
                                             InterfaceDecl *containingProto) {
   Decl *suppliedMissingMember = nullptr;

   auto handleMissingInterfaceMember =
      [&](const DeclDeserializationError &error) {
         assert(error.needsFieldOffsetVectorEntry() == 0);

         if (error.getNumberOfVTableEntries() > 0)
            containingProto->setHasMissingRequirements(true);

         suppliedMissingMember = MissingMemberDecl::create(
            context, containingProto, error.getName(),
            error.getNumberOfVTableEntries(), 0);
      };
   llvm::handleAllErrors(std::move(error), handleMissingInterfaceMember);
   return suppliedMissingMember;
}

Decl *handleErrorAndSupplyMissingMiscMember(llvm::Error &&error) {
   llvm::consumeError(std::move(error));
   return nullptr;
}

Decl *handleErrorAndSupplyMissingMember(AstContext &context, Decl *container,
                                        llvm::Error &&error) {
   // Drop the member if it had a problem.
   // FIXME: Handle overridable members in class extensions too, someday.
   if (auto *containingClass = dyn_cast<ClassDecl>(container)) {
      return handleErrorAndSupplyMissingClassMember(context, std::move(error),
                                                    containingClass);
   }
   if (auto *containingProto = dyn_cast<InterfaceDecl>(container)) {
      return handleErrorAndSupplyMissingProtoMember(context, std::move(error),
                                                    containingProto);
   }
   return handleErrorAndSupplyMissingMiscMember(std::move(error));
}

void ModuleFile::loadAllMembers(Decl *container, uint64_t contextData) {
   PrettyStackTraceDecl trace("loading members for", container);
   ++NumMemberListsLoaded;

   IterableDeclContext *IDC;
   if (auto *nominal = dyn_cast<NominalTypeDecl>(container))
      IDC = nominal;
   else
      IDC = cast<ExtensionDecl>(container);

   BCOffsetRAII restoreOffset(DeclTypeCursor);
   fatalIfNotSuccess(DeclTypeCursor.JumpToBit(contextData));
   llvm::BitstreamEntry entry = fatalIfUnexpected(DeclTypeCursor.advance());
   if (entry.Kind != llvm::BitstreamEntry::Record)
      fatal();

   SmallVector<uint64_t, 16> memberIDBuffer;

   unsigned kind =
      fatalIfUnexpected(DeclTypeCursor.readRecord(entry.ID, memberIDBuffer));
   assert(kind == decls_block::MEMBERS);
   (void)kind;

   ArrayRef<uint64_t> rawMemberIDs;
   decls_block::MembersLayout::readRecord(memberIDBuffer, rawMemberIDs);

   if (rawMemberIDs.empty())
      return;

   SmallVector<Decl *, 16> members;
   members.reserve(rawMemberIDs.size());
   for (DeclID rawID : rawMemberIDs) {
      Expected<Decl *> next = getDeclChecked(rawID);
      if (next) {
         assert(next.get() && "unchecked error deserializing next member");
         members.push_back(next.get());
      } else {
         if (!getContext().LangOpts.EnableDeserializationRecovery)
            fatal(next.takeError());

         Decl *suppliedMissingMember = handleErrorAndSupplyMissingMember(
            getContext(), container, next.takeError());
         if (suppliedMissingMember)
            members.push_back(suppliedMissingMember);
      }
   }

   for (auto member : members)
      IDC->addMember(member);

   if (auto *proto = dyn_cast<InterfaceDecl>(container)) {
      PrettyStackTraceDecl trace("reading default witness table for", proto);
      bool Err = readDefaultWitnessTable(proto);
      assert(!Err && "unable to read default witness table");
      (void)Err;
   }
}

void
ModuleFile::loadAllConformances(const Decl *D, uint64_t contextData,
                                SmallVectorImpl<InterfaceConformance*> &conformances) {
   PrettyStackTraceDecl trace("loading conformances for", D);

   uint64_t numConformances;
   uint64_t bitPosition;
   std::tie(numConformances, bitPosition)
      = decodeLazyConformanceContextData(contextData);

   BCOffsetRAII restoreOffset(DeclTypeCursor);
   fatalIfNotSuccess(DeclTypeCursor.JumpToBit(bitPosition));

   while (numConformances--) {
      auto conf = readConformance(DeclTypeCursor);
      if (conf.isConcrete())
         conformances.push_back(conf.getConcrete());
   }
}

Type
ModuleFile::loadAssociatedTypeDefault(const polar::AssociatedTypeDecl *ATD,
                                      uint64_t contextData) {
   return getType(contextData);
}

ValueDecl *ModuleFile::loadDynamicallyReplacedFunctionDecl(
   const DynamicReplacementAttr *DRA, uint64_t contextData) {
   return cast<ValueDecl>(getDecl(contextData));
}

void ModuleFile::finishNormalConformance(NormalInterfaceConformance *conformance,
                                         uint64_t contextData) {
   using namespace decls_block;

   PrettyStackTraceModuleFile traceModule("While reading from", *this);
   PrettyStackTraceConformance trace(getAssociatedModule()->getAstContext(),
                                     "finishing conformance for",
                                     conformance);
   ++NumNormalInterfaceConformancesCompleted;

   assert(conformance->isComplete());

   conformance->setState(InterfaceConformanceState::Incomplete);
   POLAR_DEFER { conformance->setState(InterfaceConformanceState::Complete); };

   // Find the conformance record.
   BCOffsetRAII restoreOffset(DeclTypeCursor);
   fatalIfNotSuccess(DeclTypeCursor.JumpToBit(contextData));
   llvm::BitstreamEntry entry = fatalIfUnexpected(DeclTypeCursor.advance());
   assert(entry.Kind == llvm::BitstreamEntry::Record &&
          "registered lazy loader incorrectly");

   DeclID protoID;
   DeclContextID contextID;
   unsigned valueCount, typeCount, conformanceCount;
   ArrayRef<uint64_t> rawIDs;
   SmallVector<uint64_t, 16> scratch;

   unsigned kind =
      fatalIfUnexpected(DeclTypeCursor.readRecord(entry.ID, scratch));
   (void) kind;
   assert(kind == NORMAL_PROTOCOL_CONFORMANCE &&
          "registered lazy loader incorrectly");
   NormalInterfaceConformanceLayout::readRecord(scratch, protoID,
                                               contextID, typeCount,
                                               valueCount, conformanceCount,
                                               rawIDs);

   // Read requirement signature conformances.
   const InterfaceDecl *proto = conformance->getInterface();
   SmallVector<InterfaceConformanceRef, 4> reqConformances;

   if (proto->isObjC() && getContext().LangOpts.EnableDeserializationRecovery) {
      // Don't crash if inherited protocols are added or removed.
      // This is limited to Objective-C protocols because we know their only
      // conformance requirements are on Self. This isn't actually a /safe/ change
      // even in Objective-C, but we mostly just don't want to crash.

      llvm::SmallDenseMap<InterfaceDecl *, InterfaceConformanceRef, 16>
         conformancesForInterfaces;
      while (conformanceCount--) {
         InterfaceConformanceRef nextConformance = readConformance(DeclTypeCursor);
         InterfaceDecl *confProto = nextConformance.getRequirement();
         conformancesForInterfaces[confProto] = nextConformance;
      }

      for (const auto &req : proto->getRequirementSignature()) {
         if (req.getKind() != RequirementKind::Conformance)
            continue;
         InterfaceDecl *proto =
            req.getSecondType()->castTo<InterfaceType>()->getDecl();
         auto iter = conformancesForInterfaces.find(proto);
         if (iter != conformancesForInterfaces.end()) {
            reqConformances.push_back(iter->getSecond());
         } else {
            // Put in an abstract conformance as a placeholder. This is a lie, but
            // there's not much better we can do. We're relying on the fact that
            // the rest of the compiler doesn't actually need to check the
            // conformance to an Objective-C protocol for anything important.
            // There are no associated types and we don't emit a Swift conformance
            // record.
            reqConformances.push_back(InterfaceConformanceRef(proto));
         }
      }

   } else {
      auto isConformanceReq = [](const Requirement &req) {
         return req.getKind() == RequirementKind::Conformance;
      };
      if (conformanceCount != llvm::count_if(proto->getRequirementSignature(),
                                             isConformanceReq)) {
         fatal(llvm::make_error<llvm::StringError>(
            "serialized conformances do not match requirement signature",
            llvm::inconvertibleErrorCode()));
      }
      while (conformanceCount--)
         reqConformances.push_back(readConformance(DeclTypeCursor));
   }
   conformance->setSignatureConformances(reqConformances);

   ArrayRef<uint64_t>::iterator rawIDIter = rawIDs.begin();

   TypeWitnessMap typeWitnesses;
   while (typeCount--) {
      // FIXME: We don't actually want to allocate an archetype here; we just
      // want to get an access path within the protocol.
      auto first = cast<AssociatedTypeDecl>(getDecl(*rawIDIter++));
      auto second = getType(*rawIDIter++);
      auto third = cast_or_null<TypeDecl>(getDecl(*rawIDIter++));
      if (third &&
          isa<TypeAliasDecl>(third) &&
          third->getModuleContext() != getAssociatedModule() &&
          !third->getDeclaredInterfaceType()->isEqual(second)) {
         // Conservatively drop references to typealiases in other modules
         // that may have changed. This may also drop references to typealiases
         // that /haven't/ changed but just happen to have generics in them, but
         // in practice having a declaration here isn't actually required by the
         // rest of the compiler.
         third = nullptr;
      }
      typeWitnesses[first] = {second, third};
   }
   assert(rawIDIter <= rawIDs.end() && "read too much");

   // Set type witnesses.
   for (auto typeWitness : typeWitnesses) {
      conformance->setTypeWitness(typeWitness.first,
                                  typeWitness.second.getWitnessType(),
                                  typeWitness.second.getWitnessDecl());
   }

   // An imported requirement may have changed type between Swift versions.
   // In this situation we need to do a post-pass to fill in missing
   // requirements with opaque witnesses.
   bool needToFillInOpaqueValueWitnesses = false;
   while (valueCount--) {
      ValueDecl *req;

      auto trySetWitness = [&](Witness w) {
         if (req)
            conformance->setWitness(req, w);
      };

      auto deserializedReq = getDeclChecked(*rawIDIter++);
      if (deserializedReq) {
         req = cast_or_null<ValueDecl>(*deserializedReq);
      } else if (getContext().LangOpts.EnableDeserializationRecovery) {
         consumeError(deserializedReq.takeError());
         req = nullptr;
         needToFillInOpaqueValueWitnesses = true;
      } else {
         fatal(deserializedReq.takeError());
      }

      bool isOpaque = false;
      ValueDecl *witness;
      auto deserializedWitness = getDeclChecked(*rawIDIter++);
      if (deserializedWitness) {
         witness = cast_or_null<ValueDecl>(*deserializedWitness);
         // Across language compatibility versions, the witnessing decl may have
         // changed its signature as seen by the current compatibility version.
         // In that case, we want the conformance to still be available, but
         // we can't make use of the relationship to the underlying decl.
      } else if (getContext().LangOpts.EnableDeserializationRecovery) {
         consumeError(deserializedWitness.takeError());
         isOpaque = true;
         witness = nullptr;
      } else {
         fatal(deserializedWitness.takeError());
      }

      assert(!req || isOpaque || witness ||
             req->getAttrs().hasAttribute<OptionalAttr>() ||
             req->getAttrs().isUnavailable(getContext()));
      if (!witness && !isOpaque) {
         trySetWitness(Witness());
         continue;
      }

      auto trySetOpaqueWitness = [&]{
         if (!req)
            return;

         conformance->setWitness(req, Witness::forOpaque(req));
      };

      // Witness substitutions.
      auto witnessSubstitutions = getSubstitutionMapChecked(*rawIDIter++);
      if (!witnessSubstitutions) {
         // Missing module errors are most likely caused by an
         // implementation-only import hiding types and decls.
         // rdar://problem/52837313
         if (witnessSubstitutions.errorIsA<XRefNonLoadedModuleError>()) {
            consumeError(witnessSubstitutions.takeError());
            isOpaque = true;
         }
         else
            fatal(witnessSubstitutions.takeError());
      }

      // Handle opaque witnesses that couldn't be deserialized.
      if (isOpaque) {
         trySetOpaqueWitness();
         continue;
      }

      // Set the witness.
      trySetWitness(Witness::forDeserialized(witness, witnessSubstitutions.get()));
   }
   assert(rawIDIter <= rawIDs.end() && "read too much");

   // Fill in opaque value witnesses if we need to.
   if (needToFillInOpaqueValueWitnesses) {
      for (auto member : proto->getMembers()) {
         // We only care about non-associated-type requirements.
         auto valueMember = dyn_cast<ValueDecl>(member);
         if (!valueMember || !valueMember->isInterfaceRequirement()
             || isa<AssociatedTypeDecl>(valueMember))
            continue;

         if (!conformance->hasWitness(valueMember))
            conformance->setWitness(valueMember, Witness::forOpaque(valueMember));
      }
   }
}

void ModuleFile::loadRequirementSignature(const InterfaceDecl *decl,
                                          uint64_t contextData,
                                          SmallVectorImpl<Requirement> &reqs) {
   BCOffsetRAII restoreOffset(DeclTypeCursor);
   fatalIfNotSuccess(DeclTypeCursor.JumpToBit(contextData));
   readGenericRequirements(reqs, DeclTypeCursor);
}

static Optional<ForeignErrorConvention::Kind>
decodeRawStableForeignErrorConventionKind(uint8_t kind) {
   switch (kind) {
      case static_cast<uint8_t>(ForeignErrorConventionKind::ZeroResult):
         return ForeignErrorConvention::ZeroResult;
      case static_cast<uint8_t>(ForeignErrorConventionKind::NonZeroResult):
         return ForeignErrorConvention::NonZeroResult;
      case static_cast<uint8_t>(ForeignErrorConventionKind::ZeroPreservedResult):
         return ForeignErrorConvention::ZeroPreservedResult;
      case static_cast<uint8_t>(ForeignErrorConventionKind::NilResult):
         return ForeignErrorConvention::NilResult;
      case static_cast<uint8_t>(ForeignErrorConventionKind::NonNilError):
         return ForeignErrorConvention::NonNilError;
      default:
         return None;
   }
}

Optional<StringRef> ModuleFile::maybeReadInlinableBodyText() {
   using namespace decls_block;

   SmallVector<uint64_t, 8> scratch;
   BCOffsetRAII restoreOffset(DeclTypeCursor);
   StringRef blobData;

   llvm::BitstreamEntry next =
      fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
   if (next.Kind != llvm::BitstreamEntry::Record)
      return None;

   unsigned recKind =
      fatalIfUnexpected(DeclTypeCursor.readRecord(next.ID, scratch, &blobData));
   if (recKind != INLINABLE_BODY_TEXT)
      return None;

   restoreOffset.reset();
   return blobData;
}

Optional<ForeignErrorConvention> ModuleFile::maybeReadForeignErrorConvention() {
   using namespace decls_block;

   SmallVector<uint64_t, 8> scratch;

   BCOffsetRAII restoreOffset(DeclTypeCursor);

   llvm::BitstreamEntry next =
      fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
   if (next.Kind != llvm::BitstreamEntry::Record)
      return None;

   unsigned recKind =
      fatalIfUnexpected(DeclTypeCursor.readRecord(next.ID, scratch));
   switch (recKind) {
      case FOREIGN_ERROR_CONVENTION:
         restoreOffset.reset();
         break;

      default:
         return None;
   }

   uint8_t rawKind;
   bool isOwned;
   bool isReplaced;
   unsigned errorParameterIndex;
   TypeID errorParameterTypeID;
   TypeID resultTypeID;
   ForeignErrorConventionLayout::readRecord(scratch, rawKind,
                                            isOwned, isReplaced,
                                            errorParameterIndex,
                                            errorParameterTypeID,
                                            resultTypeID);

   ForeignErrorConvention::Kind kind;
   if (auto optKind = decodeRawStableForeignErrorConventionKind(rawKind))
      kind = *optKind;
   else
      fatal();

   Type errorParameterType = getType(errorParameterTypeID);
   CanType canErrorParameterType;
   if (errorParameterType)
      canErrorParameterType = errorParameterType->getCanonicalType();

   Type resultType = getType(resultTypeID);
   CanType canResultType;
   if (resultType)
      canResultType = resultType->getCanonicalType();

   auto owned = isOwned ? ForeignErrorConvention::IsOwned
                        : ForeignErrorConvention::IsNotOwned;
   auto replaced = ForeignErrorConvention::IsReplaced_t(isOwned);
   switch (kind) {
      case ForeignErrorConvention::ZeroResult:
         return ForeignErrorConvention::getZeroResult(errorParameterIndex,
                                                      owned, replaced,
                                                      canErrorParameterType,
                                                      canResultType);

      case ForeignErrorConvention::NonZeroResult:
         return ForeignErrorConvention::getNonZeroResult(errorParameterIndex,
                                                         owned, replaced,
                                                         canErrorParameterType,
                                                         canResultType);

      case ForeignErrorConvention::ZeroPreservedResult:
         return ForeignErrorConvention::getZeroPreservedResult(errorParameterIndex,
                                                               owned, replaced,
                                                               canErrorParameterType);

      case ForeignErrorConvention::NilResult:
         return ForeignErrorConvention::getNilResult(errorParameterIndex,
                                                     owned, replaced,
                                                     canErrorParameterType);

      case ForeignErrorConvention::NonNilError:
         return ForeignErrorConvention::getNonNilError(errorParameterIndex,
                                                       owned, replaced,
                                                       canErrorParameterType);
   }

   llvm_unreachable("Unhandled ForeignErrorConvention in switch.");
}
